]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.cc] all: merge master (b8fcae0) into dev.cc
authorRuss Cox <rsc@golang.org>
Wed, 4 Feb 2015 21:11:28 +0000 (16:11 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 4 Feb 2015 21:12:58 +0000 (16:12 -0500)
Change-Id: I2aa1d0b0c4cf7632a54e843810959b468e3812ab

86 files changed:
.gitignore
include/libc.h
include/link.h
include/plan9/libc.h
src/cmd/asm/internal/addr/addr.go [new file with mode: 0644]
src/cmd/asm/internal/arch/arch.go [new file with mode: 0644]
src/cmd/asm/internal/asm/asm.go [new file with mode: 0644]
src/cmd/asm/internal/asm/expr_test.go [new file with mode: 0644]
src/cmd/asm/internal/asm/parse.go [new file with mode: 0644]
src/cmd/asm/internal/flags/flags.go [new file with mode: 0644]
src/cmd/asm/internal/lex/input.go [new file with mode: 0644]
src/cmd/asm/internal/lex/lex.go [new file with mode: 0644]
src/cmd/asm/internal/lex/lex_test.go [new file with mode: 0644]
src/cmd/asm/internal/lex/slice.go [new file with mode: 0644]
src/cmd/asm/internal/lex/stack.go [new file with mode: 0644]
src/cmd/asm/internal/lex/tokenizer.go [new file with mode: 0644]
src/cmd/asm/main.go [new file with mode: 0644]
src/cmd/cc/lexbody
src/cmd/dist/build.go
src/cmd/dist/buildruntime.go
src/cmd/dist/buildtool.go [new file with mode: 0644]
src/cmd/dist/util.go
src/cmd/go/build.go
src/cmd/go/main.go
src/cmd/go/pkg.go
src/cmd/internal/asm/asm.go [new file with mode: 0644]
src/cmd/internal/asm/lexbody.go [new file with mode: 0644]
src/cmd/internal/asm/macbody.go [new file with mode: 0644]
src/cmd/internal/obj/arm/5.out.go [new file with mode: 0644]
src/cmd/internal/obj/arm/anames5.go [new file with mode: 0644]
src/cmd/internal/obj/arm/asm5.go [new file with mode: 0644]
src/cmd/internal/obj/arm/list5.go [new file with mode: 0644]
src/cmd/internal/obj/arm/obj5.go [new file with mode: 0644]
src/cmd/internal/obj/arm/util.go [new file with mode: 0644]
src/cmd/internal/obj/data.go [new file with mode: 0644]
src/cmd/internal/obj/fmt.go [new file with mode: 0644]
src/cmd/internal/obj/funcdata.go [new file with mode: 0644]
src/cmd/internal/obj/go.go [new file with mode: 0644]
src/cmd/internal/obj/i386/8.out.go [new file with mode: 0644]
src/cmd/internal/obj/i386/anames8.go [new file with mode: 0644]
src/cmd/internal/obj/i386/asm8.go [new file with mode: 0644]
src/cmd/internal/obj/i386/list8.go [new file with mode: 0644]
src/cmd/internal/obj/i386/obj8.go [new file with mode: 0644]
src/cmd/internal/obj/i386/util.go [new file with mode: 0644]
src/cmd/internal/obj/ld.go [new file with mode: 0644]
src/cmd/internal/obj/link.go [new file with mode: 0644]
src/cmd/internal/obj/obj.go [new file with mode: 0644]
src/cmd/internal/obj/objfile.go [new file with mode: 0644]
src/cmd/internal/obj/pass.go [new file with mode: 0644]
src/cmd/internal/obj/pcln.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/9.out.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/anames9.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/asm9.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/list9.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/obj9.go [new file with mode: 0644]
src/cmd/internal/obj/ppc64/util.go [new file with mode: 0644]
src/cmd/internal/obj/stack.go [new file with mode: 0644]
src/cmd/internal/obj/sym.go [new file with mode: 0644]
src/cmd/internal/obj/textflag.go [new file with mode: 0644]
src/cmd/internal/obj/util.go [new file with mode: 0644]
src/cmd/internal/obj/x86/6.out.go [new file with mode: 0644]
src/cmd/internal/obj/x86/anames6.go [new file with mode: 0644]
src/cmd/internal/obj/x86/asm6.go [new file with mode: 0644]
src/cmd/internal/obj/x86/list6.go [new file with mode: 0644]
src/cmd/internal/obj/x86/obj6.go [new file with mode: 0644]
src/cmd/internal/obj/x86/util.go [new file with mode: 0644]
src/cmd/new5a/a.y [new file with mode: 0644]
src/cmd/new5a/lex.go [new file with mode: 0644]
src/cmd/new5a/y.go [new file with mode: 0644]
src/cmd/new6a/a.y [new file with mode: 0644]
src/cmd/new6a/lex.go [new file with mode: 0644]
src/cmd/new6a/y.go [new file with mode: 0644]
src/cmd/new8a/a.y [new file with mode: 0644]
src/cmd/new8a/lex.go [new file with mode: 0644]
src/cmd/new8a/y.go [new file with mode: 0644]
src/cmd/new9a/a.y [new file with mode: 0644]
src/cmd/new9a/lex.go [new file with mode: 0644]
src/cmd/new9a/y.go [new file with mode: 0644]
src/cmd/objwriter/main.go [new file with mode: 0644]
src/lib9/goos.c
src/lib9/run_windows.c
src/liblink/objfile.c
src/liblink/objfilego.c [new file with mode: 0644]
src/make.bash
src/make.bat
src/make.rc

index 7b63aaf3d4d5276e2a8cfbca112c4bb883bf176b..585cd0f12ba190f9baceb32291cc7bfa444fea53 100644 (file)
@@ -26,15 +26,14 @@ misc/cgo/life/run.out
 misc/cgo/stdio/run.out
 misc/cgo/testso/main
 misc/dashboard/builder/builder
-src/cmd/?a/y.output
 src/liblink/anames?.c
-src/cmd/cc/y.output
+src/cmd/*/y.output
 src/cmd/cgo/zdefaultcc.go
 src/cmd/dist/dist.dSYM
 src/cmd/gc/mkbuiltin1
 src/cmd/gc/opnames.h
-src/cmd/gc/y.output
 src/cmd/go/zdefaultcc.go
+src/cmd/internal/obj/zbootstrap.go
 src/go/doc/headscan
 src/runtime/mkversion
 src/runtime/zaexperiment.h
index e4d879907720ad3a874ff6c38eef77346069399d..d82a19ccce8f3b78f8fdb92e7f681484fffb5f81 100644 (file)
@@ -292,6 +292,8 @@ extern      char*   getgoversion(void);
 extern char*   getgoarm(void);
 extern char*   getgo386(void);
 extern char*   getgoextlinkenabled(void);
+extern char*   getgohostos(void);
+extern char*   getgohostarch(void);
 
 extern char*   mktempdir(void);
 extern void    removeall(char*);
index 91993986b3f24b4cb8b243d980378ffc62423d40..bc0a96026a8f940c59193c69f4a49e11246775c2 100644 (file)
@@ -241,6 +241,7 @@ struct      Prog
        uchar   ft;     // oclass cache
        uchar   tt;     // oclass cache
        uchar   isize;  // amd64, 386
+       uchar   printed;
 
        char    width;  /* fake for DATA */
        char    mode;   /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
@@ -300,6 +301,7 @@ struct      LSym
        uchar   localentry;     // ppc64: instrs between global & local entry
        uchar   seenglobl;
        uchar   onlist; // on the textp or datap lists
+       uchar   printed;
        int16   symid;  // for writing .5/.6/.8 files
        int32   dynid;
        int32   sig;
@@ -455,6 +457,7 @@ struct      Hist
        char*   name;
        int32   line;
        int32   offset;
+       uchar   printed;
 };
 
 struct Plist
index 773edeee3f7623947c620ce0b9760f345767e5ec..9a880505a4d91348e02b6363cb02a1476855257e 100644 (file)
@@ -14,6 +14,10 @@ char*        getgoversion(void);
 char*  getgoarm(void);
 char*  getgo386(void);
 char*  getgoextlinkenabled(void);
+char*  getgohostos(void);
+char*  getgohostarch(void);
+
+int    runcmd(char**);
 
 void   flagcount(char*, char*, int*);
 void   flagint32(char*, char*, int32*);
diff --git a/src/cmd/asm/internal/addr/addr.go b/src/cmd/asm/internal/addr/addr.go
new file mode 100644 (file)
index 0000000..b82af7e
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package addr holds the definition of an instruction address.
+package addr
+
+// Addr represents a parsed address.
+type Addr struct {
+       IsStatic            bool    // symbol<>
+       IsImmediateConstant bool    // $3
+       IsImmediateAddress  bool    // $main·main(SB)
+       IsIndirect          bool    // (R1)
+       HasRegister         bool    // register is set
+       HasRegister2        bool    // register2 is set
+       HasFloat            bool    // float is set
+       HasOffset           bool    // offset is set
+       HasString           bool    // string is set
+       Symbol              string  // "main·main"
+       Register            int16   // R1
+       Register2           int16   // R1 in R0:R1
+       Offset              int64   // 3
+       Float               float64 // 1.0e2 (floating constant)
+       String              string  // "hi" (string constant)
+       Index               int16   // R1 in (R1*8)
+       Scale               int8    // 8 in (R1*8)
+}
+
+const (
+       // IsStatic does not appear here; Is and Has methods ignore it.
+       ImmediateConstant = 1 << iota
+       ImmediateAddress
+       Indirect
+       Symbol
+       Register
+       Register2
+       Offset
+       Float
+       String
+       Index
+       Scale
+)
+
+// Has reports whether the address has any of the specified elements.
+// Indirect and immediate are not checked.
+func (a *Addr) Has(mask int) bool {
+       if mask&Symbol != 0 && a.Symbol != "" {
+               return true
+       }
+       if mask&Register != 0 && a.HasRegister {
+               return true
+       }
+       if mask&Register2 != 0 && a.HasRegister2 {
+               return true
+       }
+       if mask&Offset != 0 && a.HasOffset {
+               return true
+       }
+       if mask&Float != 0 && a.HasFloat {
+               return true
+       }
+       if mask&String != 0 && a.HasString {
+               return true
+       }
+       if mask&Index != 0 && a.Index != 0 {
+               return true
+       }
+       if mask&Scale != 0 && a.Scale != 0 {
+               return true
+       }
+       return false
+}
+
+// Is reports whether the address has all the specified elements.
+// Indirect and immediate are checked.
+func (a *Addr) Is(mask int) bool {
+       if (mask&ImmediateConstant == 0) != !a.IsImmediateConstant {
+               return false
+       }
+       if (mask&ImmediateAddress == 0) != !a.IsImmediateAddress {
+               return false
+       }
+       if (mask&Indirect == 0) != !a.IsIndirect {
+               return false
+       }
+       if (mask&Symbol == 0) != (a.Symbol == "") {
+               return false
+       }
+       if (mask&Register == 0) != !a.HasRegister {
+               return false
+       }
+       if (mask&Register2 == 0) != !a.HasRegister2 {
+               return false
+       }
+       if (mask&Offset == 0) != !a.HasOffset {
+               // $0 has the immediate bit but value 0.
+               return false
+       }
+       if (mask&Float == 0) != !a.HasFloat {
+               return false
+       }
+       if (mask&String == 0) != !a.HasString {
+               return false
+       }
+       if (mask&Index == 0) != (a.Index == 0) {
+               return false
+       }
+       if (mask&Scale == 0) != (a.Scale == 0) {
+               return false
+       }
+       return true
+}
diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go
new file mode 100644 (file)
index 0000000..a318fa1
--- /dev/null
@@ -0,0 +1,292 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package arch
+
+import (
+       "cmd/internal/obj"
+       "cmd/internal/obj/i386" // == 386
+       "cmd/internal/obj/x86"  // == amd64
+)
+
+// Pseudo-registers whose names are the constant name without the leading R.
+const (
+       RFP = -(iota + 1)
+       RSB
+       RSP
+       RPC
+)
+
+// Arch wraps the link architecture object with more architecture-specific information.
+type Arch struct {
+       *obj.LinkArch
+       D_INDIR  int // TODO: why not in LinkArch?
+       D_CONST2 int // TODO: why not in LinkArch?
+       // Register number of hardware stack pointer.
+       SP int
+       // Encoding of non-address.
+       NoAddr obj.Addr
+       // Map of instruction names to enumeration.
+       Instructions map[string]int
+       // Map of register names to enumeration.
+       Registers map[string]int
+       // Map of pseudo-instructions (TEXT, DATA etc.)  to enumeration.
+       Pseudos map[string]int
+       // Instructions that take one operand whose result is a destination.
+       UnaryDestination map[int]bool
+}
+
+// Set configures the architecture specified by GOARCH and returns its representation.
+// It returns nil if GOARCH is not recognized.
+func Set(GOARCH string) *Arch {
+       // TODO: Is this how to set this up?
+       switch GOARCH {
+       case "386":
+               return arch386()
+       case "amd64":
+               return archAmd64()
+       }
+       return nil
+}
+
+func arch386() *Arch {
+       noAddr := obj.Addr{
+               Type:  i386.D_NONE,
+               Index: i386.D_NONE,
+       }
+
+       registers := make(map[string]int)
+       // Create maps for easy lookup of instruction names etc.
+       // TODO: Should this be done in obj for us?
+       for i, s := range i386.Register {
+               registers[s] = i
+       }
+       // Pseudo-registers.
+       registers["SB"] = RSB
+       registers["FP"] = RFP
+       registers["SP"] = RSP
+       registers["PC"] = RPC
+
+       instructions := make(map[string]int)
+       for i, s := range i386.Anames {
+               instructions[s] = i
+       }
+       // Annoying aliases.
+       instructions["JA"] = i386.AJHI
+       instructions["JAE"] = i386.AJCC
+       instructions["JB"] = i386.AJCS
+       instructions["JBE"] = i386.AJLS
+       instructions["JC"] = i386.AJCS
+       instructions["JE"] = i386.AJEQ
+       instructions["JG"] = i386.AJGT
+       instructions["JHS"] = i386.AJCC
+       instructions["JL"] = i386.AJLT
+       instructions["JLO"] = i386.AJCS
+       instructions["JNA"] = i386.AJLS
+       instructions["JNAE"] = i386.AJCS
+       instructions["JNB"] = i386.AJCC
+       instructions["JNBE"] = i386.AJHI
+       instructions["JNC"] = i386.AJCC
+       instructions["JNG"] = i386.AJLE
+       instructions["JNGE"] = i386.AJLT
+       instructions["JNL"] = i386.AJGE
+       instructions["JNLE"] = i386.AJGT
+       instructions["JNO"] = i386.AJOC
+       instructions["JNP"] = i386.AJPC
+       instructions["JNS"] = i386.AJPL
+       instructions["JNZ"] = i386.AJNE
+       instructions["JO"] = i386.AJOS
+       instructions["JP"] = i386.AJPS
+       instructions["JPE"] = i386.AJPS
+       instructions["JPO"] = i386.AJPC
+       instructions["JS"] = i386.AJMI
+       instructions["JZ"] = i386.AJEQ
+       instructions["MASKMOVDQU"] = i386.AMASKMOVOU
+       instructions["MOVOA"] = i386.AMOVO
+       instructions["MOVNTDQ"] = i386.AMOVNTO
+
+       pseudos := make(map[string]int) // TEXT, DATA etc.
+       pseudos["DATA"] = i386.ADATA
+       pseudos["FUNCDATA"] = i386.AFUNCDATA
+       pseudos["GLOBL"] = i386.AGLOBL
+       pseudos["PCDATA"] = i386.APCDATA
+       pseudos["TEXT"] = i386.ATEXT
+
+       unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
+       // These instructions write to prog.To.
+       unaryDestination[i386.ABSWAPL] = true
+       unaryDestination[i386.ACMPXCHG8B] = true
+       unaryDestination[i386.ADECB] = true
+       unaryDestination[i386.ADECL] = true
+       unaryDestination[i386.ADECW] = true
+       unaryDestination[i386.AINCB] = true
+       unaryDestination[i386.AINCL] = true
+       unaryDestination[i386.AINCW] = true
+       unaryDestination[i386.ANEGB] = true
+       unaryDestination[i386.ANEGL] = true
+       unaryDestination[i386.ANEGW] = true
+       unaryDestination[i386.ANOTB] = true
+       unaryDestination[i386.ANOTL] = true
+       unaryDestination[i386.ANOTW] = true
+       unaryDestination[i386.APOPL] = true
+       unaryDestination[i386.APOPW] = true
+       unaryDestination[i386.ASETCC] = true
+       unaryDestination[i386.ASETCS] = true
+       unaryDestination[i386.ASETEQ] = true
+       unaryDestination[i386.ASETGE] = true
+       unaryDestination[i386.ASETGT] = true
+       unaryDestination[i386.ASETHI] = true
+       unaryDestination[i386.ASETLE] = true
+       unaryDestination[i386.ASETLS] = true
+       unaryDestination[i386.ASETLT] = true
+       unaryDestination[i386.ASETMI] = true
+       unaryDestination[i386.ASETNE] = true
+       unaryDestination[i386.ASETOC] = true
+       unaryDestination[i386.ASETOS] = true
+       unaryDestination[i386.ASETPC] = true
+       unaryDestination[i386.ASETPL] = true
+       unaryDestination[i386.ASETPS] = true
+       unaryDestination[i386.AFFREE] = true
+       unaryDestination[i386.AFLDENV] = true
+       unaryDestination[i386.AFSAVE] = true
+       unaryDestination[i386.AFSTCW] = true
+       unaryDestination[i386.AFSTENV] = true
+       unaryDestination[i386.AFSTSW] = true
+
+       return &Arch{
+               LinkArch:         &i386.Link386,
+               D_INDIR:          i386.D_INDIR,
+               D_CONST2:         i386.D_CONST2,
+               SP:               i386.D_SP,
+               NoAddr:           noAddr,
+               Instructions:     instructions,
+               Registers:        registers,
+               Pseudos:          pseudos,
+               UnaryDestination: unaryDestination,
+       }
+}
+
+func archAmd64() *Arch {
+       noAddr := obj.Addr{
+               Type:  x86.D_NONE,
+               Index: x86.D_NONE,
+       }
+
+       registers := make(map[string]int)
+       // Create maps for easy lookup of instruction names etc.
+       // TODO: Should this be done in obj for us?
+       for i, s := range x86.Register {
+               registers[s] = i
+       }
+       // Pseudo-registers.
+       registers["SB"] = RSB
+       registers["FP"] = RFP
+       registers["SP"] = RSP
+       registers["PC"] = RPC
+
+       instructions := make(map[string]int)
+       for i, s := range x86.Anames {
+               instructions[s] = i
+       }
+       // Annoying aliases.
+       instructions["JB"] = x86.AJCS
+       instructions["JC"] = x86.AJCS
+       instructions["JNAE"] = x86.AJCS
+       instructions["JLO"] = x86.AJCS
+       instructions["JAE"] = x86.AJCC
+       instructions["JNB"] = x86.AJCC
+       instructions["JNC"] = x86.AJCC
+       instructions["JHS"] = x86.AJCC
+       instructions["JE"] = x86.AJEQ
+       instructions["JZ"] = x86.AJEQ
+       instructions["JNZ"] = x86.AJNE
+       instructions["JBE"] = x86.AJLS
+       instructions["JNA"] = x86.AJLS
+       instructions["JA"] = x86.AJHI
+       instructions["JNBE"] = x86.AJHI
+       instructions["JS"] = x86.AJMI
+       instructions["JNS"] = x86.AJPL
+       instructions["JP"] = x86.AJPS
+       instructions["JPE"] = x86.AJPS
+       instructions["JNP"] = x86.AJPC
+       instructions["JPO"] = x86.AJPC
+       instructions["JL"] = x86.AJLT
+       instructions["JNGE"] = x86.AJLT
+       instructions["JNL"] = x86.AJGE
+       instructions["JNG"] = x86.AJLE
+       instructions["JG"] = x86.AJGT
+       instructions["JNLE"] = x86.AJGT
+       instructions["MASKMOVDQU"] = x86.AMASKMOVOU
+       instructions["MOVD"] = x86.AMOVQ
+       instructions["MOVDQ2Q"] = x86.AMOVQ
+
+       pseudos := make(map[string]int) // TEXT, DATA etc.
+       pseudos["DATA"] = x86.ADATA
+       pseudos["FUNCDATA"] = x86.AFUNCDATA
+       pseudos["GLOBL"] = x86.AGLOBL
+       pseudos["PCDATA"] = x86.APCDATA
+       pseudos["TEXT"] = x86.ATEXT
+
+       unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
+       // These instructions write to prog.To.
+       unaryDestination[x86.ABSWAPL] = true
+       unaryDestination[x86.ABSWAPQ] = true
+       unaryDestination[x86.ACMPXCHG8B] = true
+       unaryDestination[x86.ADECB] = true
+       unaryDestination[x86.ADECL] = true
+       unaryDestination[x86.ADECQ] = true
+       unaryDestination[x86.ADECW] = true
+       unaryDestination[x86.AINCB] = true
+       unaryDestination[x86.AINCL] = true
+       unaryDestination[x86.AINCQ] = true
+       unaryDestination[x86.AINCW] = true
+       unaryDestination[x86.ANEGB] = true
+       unaryDestination[x86.ANEGL] = true
+       unaryDestination[x86.ANEGQ] = true
+       unaryDestination[x86.ANEGW] = true
+       unaryDestination[x86.ANOTB] = true
+       unaryDestination[x86.ANOTL] = true
+       unaryDestination[x86.ANOTQ] = true
+       unaryDestination[x86.ANOTW] = true
+       unaryDestination[x86.APOPL] = true
+       unaryDestination[x86.APOPQ] = true
+       unaryDestination[x86.APOPW] = true
+       unaryDestination[x86.ASETCC] = true
+       unaryDestination[x86.ASETCS] = true
+       unaryDestination[x86.ASETEQ] = true
+       unaryDestination[x86.ASETGE] = true
+       unaryDestination[x86.ASETGT] = true
+       unaryDestination[x86.ASETHI] = true
+       unaryDestination[x86.ASETLE] = true
+       unaryDestination[x86.ASETLS] = true
+       unaryDestination[x86.ASETLT] = true
+       unaryDestination[x86.ASETMI] = true
+       unaryDestination[x86.ASETNE] = true
+       unaryDestination[x86.ASETOC] = true
+       unaryDestination[x86.ASETOS] = true
+       unaryDestination[x86.ASETPC] = true
+       unaryDestination[x86.ASETPL] = true
+       unaryDestination[x86.ASETPS] = true
+       unaryDestination[x86.AFFREE] = true
+       unaryDestination[x86.AFLDENV] = true
+       unaryDestination[x86.AFSAVE] = true
+       unaryDestination[x86.AFSTCW] = true
+       unaryDestination[x86.AFSTENV] = true
+       unaryDestination[x86.AFSTSW] = true
+       unaryDestination[x86.AFXSAVE] = true
+       unaryDestination[x86.AFXSAVE64] = true
+       unaryDestination[x86.ASTMXCSR] = true
+
+       return &Arch{
+               LinkArch:         &x86.Linkamd64,
+               D_INDIR:          x86.D_INDIR,
+               D_CONST2:         x86.D_NONE,
+               SP:               x86.D_SP,
+               NoAddr:           noAddr,
+               Instructions:     instructions,
+               Registers:        registers,
+               Pseudos:          pseudos,
+               UnaryDestination: unaryDestination,
+       }
+}
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
new file mode 100644 (file)
index 0000000..ae4f6af
--- /dev/null
@@ -0,0 +1,581 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asm
+
+import (
+       "fmt"
+       "strings"
+       "text/scanner"
+
+       "cmd/asm/internal/addr"
+       "cmd/asm/internal/arch"
+       "cmd/asm/internal/flags"
+       "cmd/asm/internal/lex"
+       "cmd/internal/obj"
+)
+
+// TODO: This package has many numeric conversions that should be unnecessary.
+
+// symbolType returns the extern/static etc. type appropriate for the symbol.
+func (p *Parser) symbolType(a *addr.Addr) int {
+       switch a.Register {
+       case arch.RFP:
+               return p.arch.D_PARAM
+       case arch.RSP:
+               return p.arch.D_AUTO
+       case arch.RSB:
+               // See comment in addrToAddr.
+               if a.IsImmediateAddress {
+                       return p.arch.D_ADDR
+               }
+               if a.IsStatic {
+                       return p.arch.D_STATIC
+               }
+               return p.arch.D_EXTERN
+       }
+       p.errorf("invalid register for symbol %s", a.Symbol)
+       return 0
+}
+
+// staticVersion reports whether the data's Symbol has <>, as in data<>.
+// It returns 1 for static, 0 for non-static, because that's what obj wants.
+func staticVersion(a *addr.Addr) int {
+       if a.Symbol != "" && a.IsStatic {
+               return 1
+       }
+       return 0
+}
+
+// TODO: configure the architecture
+
+// TODO: This is hacky and irregular. When obj settles down, rewrite for simplicity.
+func (p *Parser) addrToAddr(a *addr.Addr) obj.Addr {
+       out := p.arch.NoAddr
+       if a.Has(addr.Symbol) {
+               // How to encode the symbols:
+               // syntax = Typ,Index
+               // $a(SB) = ADDR,EXTERN
+               // $a<>(SB) = ADDR,STATIC
+               // a(SB) = EXTERN,NONE
+               // a<>(SB) = STATIC,NONE
+               // The call to symbolType does the first column; we need to fix up Index here.
+               out.Type = int16(p.symbolType(a))
+               if a.IsImmediateAddress {
+                       // Index field says whether it's a static.
+                       switch a.Register {
+                       case arch.RSB:
+                               if a.IsStatic {
+                                       out.Index = uint8(p.arch.D_STATIC)
+                               } else {
+                                       out.Index = uint8(p.arch.D_EXTERN)
+                               }
+                       default:
+                               p.errorf("can't handle immediate address of %s not (SB)\n", a.Symbol)
+                       }
+               }
+               out.Sym = obj.Linklookup(p.linkCtxt, a.Symbol, staticVersion(a))
+       } else if a.Has(addr.Register) {
+               // TODO: SP is tricky, and this isn't good enough.
+               // SP = D_SP
+               // 4(SP) = 4(D_SP)
+               // x+4(SP) = D_AUTO with sym=x TODO
+               out.Type = a.Register
+               if a.Register == arch.RSP {
+                       out.Type = int16(p.arch.SP)
+               }
+               if a.IsIndirect {
+                       out.Type += int16(p.arch.D_INDIR)
+               }
+               // a.Register2 handled in the instruction method; it's bizarre.
+       }
+       if a.Has(addr.Index) {
+               out.Index = uint8(a.Index) // TODO: out.Index == p.NoArch.Index should be same type as Register.
+       }
+       if a.Has(addr.Scale) {
+               out.Scale = a.Scale
+       }
+       if a.Has(addr.Offset) {
+               out.Offset = a.Offset
+               if a.Is(addr.Offset) {
+                       // RHS of MOVL $0xf1, 0xf1  // crash
+                       out.Type = int16(p.arch.D_INDIR + p.arch.D_NONE)
+               } else if a.IsImmediateConstant && out.Type == int16(p.arch.D_NONE) {
+                       out.Type = int16(p.arch.D_CONST)
+               }
+       }
+       if a.Has(addr.Float) {
+               out.U.Dval = a.Float
+               out.Type = int16(p.arch.D_FCONST)
+       }
+       if a.Has(addr.String) {
+               out.U.Sval = a.String
+               out.Type = int16(p.arch.D_SCONST)
+       }
+       // TODO from https://go-review.googlesource.com/#/c/3196/ {
+       // There's a general rule underlying this special case and the one at line 91 (RHS OF MOVL $0xf1).
+       //      Unless there's a $, it's an indirect.
+       // 4(R1)(R2*8)
+       // 4(R1)
+       // 4(R2*8)
+       // 4
+       // (R1)(R2*8)
+       // (R1)
+       // (R2*8)
+       // There should be a more general approach that doesn't just pick off cases.
+       // }
+       if a.IsIndirect && !a.Has(addr.Register) && a.Has(addr.Index) {
+               // LHS of LEAQ  0(BX*8), CX
+               out.Type = int16(p.arch.D_INDIR + p.arch.D_NONE)
+       }
+       return out
+}
+
+func (p *Parser) append(prog *obj.Prog, doLabel bool) {
+       if p.firstProg == nil {
+               p.firstProg = prog
+       } else {
+               p.lastProg.Link = prog
+       }
+       p.lastProg = prog
+       if doLabel {
+               p.pc++
+               for _, label := range p.pendingLabels {
+                       if p.labels[label] != nil {
+                               p.errorf("label %q multiply defined", label)
+                       }
+                       p.labels[label] = prog
+               }
+               p.pendingLabels = p.pendingLabels[0:0]
+       }
+       prog.Pc = int64(p.pc)
+       if *flags.Debug {
+               fmt.Println(p.histLineNum, prog)
+       }
+}
+
+// asmText assembles a TEXT pseudo-op.
+// TEXT runtime·sigtramp(SB),4,$0-0
+func (p *Parser) asmText(word string, operands [][]lex.Token) {
+       if len(operands) != 2 && len(operands) != 3 {
+               p.errorf("expect two or three operands for TEXT")
+       }
+
+       // Labels are function scoped. Patch existing labels and
+       // create a new label space for this TEXT.
+       p.patch()
+       p.labels = make(map[string]*obj.Prog)
+
+       // Operand 0 is the symbol name in the form foo(SB).
+       // That means symbol plus indirect on SB and no offset.
+       nameAddr := p.address(operands[0])
+       if !nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Register != arch.RSB {
+               p.errorf("TEXT symbol %q must be an offset from SB", nameAddr.Symbol)
+       }
+       name := nameAddr.Symbol
+       next := 1
+
+       // Next operand is the optional text flag, a literal integer.
+       flag := int8(0)
+       if len(operands) == 3 {
+               flagAddr := p.address(operands[next])
+               if !flagAddr.Is(addr.Offset) {
+                       p.errorf("TEXT flag for %s must be an integer", name)
+               }
+               flag = int8(flagAddr.Offset)
+               next++
+       }
+
+       // Next operand is the frame and arg size.
+       // Bizarre syntax: $frameSize-argSize is two words, not subtraction.
+       // Both frameSize and argSize must be simple integers; only frameSize
+       // can be negative.
+       // The "-argSize" may be missing; if so, set it to obj.ArgsSizeUnknown.
+       // Parse left to right.
+       op := operands[next]
+       if len(op) < 2 || op[0].ScanToken != '$' {
+               p.errorf("TEXT %s: frame size must be an immediate constant", name)
+       }
+       op = op[1:]
+       negative := false
+       if op[0].ScanToken == '-' {
+               negative = true
+               op = op[1:]
+       }
+       if len(op) == 0 || op[0].ScanToken != scanner.Int {
+               p.errorf("TEXT %s: frame size must be an immediate constant", name)
+       }
+       frameSize := p.positiveAtoi(op[0].String())
+       if negative {
+               frameSize = -frameSize
+       }
+       op = op[1:]
+       argSize := int64(obj.ArgsSizeUnknown)
+       if len(op) > 0 {
+               // There is an argument size. It must be a minus sign followed by a non-negative integer literal.
+               if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {
+                       p.errorf("TEXT %s: argument size must be of form -integer", name)
+               }
+               argSize = p.positiveAtoi(op[1].String())
+       }
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               As:     int16(p.arch.ATEXT),
+               Lineno: int32(p.histLineNum),
+               From: obj.Addr{
+                       Type:  int16(p.symbolType(&nameAddr)),
+                       Index: uint8(p.arch.D_NONE),
+                       Sym:   obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+                       Scale: flag,
+               },
+               To: obj.Addr{
+                       Index: uint8(p.arch.D_NONE),
+               },
+       }
+
+       // Encoding of frameSize and argSize depends on architecture.
+       switch p.arch.Thechar {
+       case '6':
+               prog.To.Type = int16(p.arch.D_CONST)
+               prog.To.Offset = (argSize << 32) | frameSize
+       case '8':
+               prog.To.Type = int16(p.arch.D_CONST2)
+               prog.To.Offset = frameSize
+               prog.To.Offset2 = int32(argSize)
+       default:
+               p.errorf("internal error: can't encode TEXT $arg-frame")
+       }
+
+       p.append(prog, true)
+}
+
+// asmData assembles a DATA pseudo-op.
+// DATA masks<>+0x00(SB)/4, $0x00000000
+func (p *Parser) asmData(word string, operands [][]lex.Token) {
+       if len(operands) != 2 {
+               p.errorf("expect two operands for DATA")
+       }
+
+       // Operand 0 has the general form foo<>+0x04(SB)/4.
+       op := operands[0]
+       n := len(op)
+       if n < 3 || op[n-2].ScanToken != '/' || op[n-1].ScanToken != scanner.Int {
+               p.errorf("expect /size for DATA argument")
+       }
+       scale := p.scale(op[n-1].String())
+       op = op[:n-2]
+       nameAddr := p.address(op)
+       ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+       if !ok || nameAddr.Register != arch.RSB {
+               p.errorf("DATA symbol %q must be an offset from SB", nameAddr.Symbol)
+       }
+       name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+
+       // Operand 1 is an immediate constant or address.
+       valueAddr := p.address(operands[1])
+       if !valueAddr.IsImmediateConstant && !valueAddr.IsImmediateAddress {
+               p.errorf("DATA value must be an immediate constant or address")
+       }
+
+       // The addresses must not overlap. Easiest test: require monotonicity.
+       if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {
+               p.errorf("overlapping DATA entry for %s", nameAddr.Symbol)
+       }
+       p.dataAddr[name] = nameAddr.Offset + int64(scale)
+
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               As:     int16(p.arch.ADATA),
+               Lineno: int32(p.histLineNum),
+               From: obj.Addr{
+                       Type:   int16(p.symbolType(&nameAddr)),
+                       Index:  uint8(p.arch.D_NONE),
+                       Sym:    obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+                       Offset: nameAddr.Offset,
+                       Scale:  scale,
+               },
+               To: p.addrToAddr(&valueAddr),
+       }
+
+       p.append(prog, false)
+}
+
+// asmGlobl assembles a GLOBL pseudo-op.
+// GLOBL shifts<>(SB),8,$256
+// GLOBL shifts<>(SB),$256
+func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
+       if len(operands) != 2 && len(operands) != 3 {
+               p.errorf("expect two or three operands for GLOBL")
+       }
+
+       // Operand 0 has the general form foo<>+0x04(SB).
+       nameAddr := p.address(operands[0])
+       ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+       if !ok || nameAddr.Register != arch.RSB {
+               p.errorf("GLOBL symbol %q must be an offset from SB", nameAddr.Symbol)
+       }
+       name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+
+       // If three operands, middle operand is a scale.
+       scale := int8(0)
+       op := operands[1]
+       if len(operands) == 3 {
+               scaleAddr := p.address(op)
+               if !scaleAddr.Is(addr.Offset) {
+                       p.errorf("GLOBL scale must be a constant")
+               }
+               scale = int8(scaleAddr.Offset)
+               op = operands[2]
+       }
+
+       // Final operand is an immediate constant.
+       sizeAddr := p.address(op)
+       if !sizeAddr.Is(addr.ImmediateConstant | addr.Offset) {
+               p.errorf("GLOBL size must be an immediate constant")
+       }
+       size := sizeAddr.Offset
+
+       // log.Printf("GLOBL %s %d, $%d", name, scale, size)
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               As:     int16(p.arch.AGLOBL),
+               Lineno: int32(p.histLineNum),
+               From: obj.Addr{
+                       Type:   int16(p.symbolType(&nameAddr)),
+                       Index:  uint8(p.arch.D_NONE),
+                       Sym:    obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+                       Offset: nameAddr.Offset,
+                       Scale:  scale,
+               },
+               To: obj.Addr{
+                       Type:   int16(p.arch.D_CONST),
+                       Index:  uint8(p.arch.D_NONE),
+                       Offset: size,
+               },
+       }
+       p.append(prog, false)
+}
+
+// asmPCData assembles a PCDATA pseudo-op.
+// PCDATA $2, $705
+func (p *Parser) asmPCData(word string, operands [][]lex.Token) {
+       if len(operands) != 2 {
+               p.errorf("expect two operands for PCDATA")
+       }
+
+       // Operand 0 must be an immediate constant.
+       addr0 := p.address(operands[0])
+       if !addr0.Is(addr.ImmediateConstant | addr.Offset) {
+               p.errorf("PCDATA value must be an immediate constant")
+       }
+       value0 := addr0.Offset
+
+       // Operand 1 must be an immediate constant.
+       addr1 := p.address(operands[1])
+       if !addr1.Is(addr.ImmediateConstant | addr.Offset) {
+               p.errorf("PCDATA value must be an immediate constant")
+       }
+       value1 := addr1.Offset
+
+       // log.Printf("PCDATA $%d, $%d", value0, value1)
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               As:     int16(p.arch.APCDATA),
+               Lineno: int32(p.histLineNum),
+               From: obj.Addr{
+                       Type:   int16(p.arch.D_CONST),
+                       Index:  uint8(p.arch.D_NONE),
+                       Offset: value0,
+               },
+               To: obj.Addr{
+                       Type:   int16(p.arch.D_CONST),
+                       Index:  uint8(p.arch.D_NONE),
+                       Offset: value1,
+               },
+       }
+       p.append(prog, true)
+}
+
+// asmFuncData assembles a FUNCDATA pseudo-op.
+// FUNCDATA $1, funcdata<>+4(SB)
+func (p *Parser) asmFuncData(word string, operands [][]lex.Token) {
+       if len(operands) != 2 {
+               p.errorf("expect two operands for FUNCDATA")
+       }
+
+       // Operand 0 must be an immediate constant.
+       valueAddr := p.address(operands[0])
+       if !valueAddr.Is(addr.ImmediateConstant | addr.Offset) {
+               p.errorf("FUNCDATA value must be an immediate constant")
+       }
+       value0 := valueAddr.Offset
+
+       // Operand 1 is a symbol name in the form foo(SB).
+       // That means symbol plus indirect on SB and no offset.
+       nameAddr := p.address(operands[1])
+       ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+       if !ok || nameAddr.Register != arch.RSB {
+               p.errorf("FUNCDATA symbol %q must be an offset from SB", nameAddr.Symbol)
+       }
+       name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+       value1 := nameAddr.Offset
+
+       // log.Printf("FUNCDATA $%d, %d", value0, value1)
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               As:     int16(p.arch.AFUNCDATA),
+               Lineno: int32(p.histLineNum),
+               From: obj.Addr{
+                       Type:   int16(p.arch.D_CONST),
+                       Index:  uint8(p.arch.D_NONE),
+                       Offset: value0,
+               },
+               To: obj.Addr{
+                       Type:   int16(p.symbolType(&nameAddr)),
+                       Index:  uint8(p.arch.D_NONE),
+                       Sym:    obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+                       Offset: value1,
+               },
+       }
+       p.append(prog, true)
+}
+
+// asmJump assembles a jump instruction.
+// JMP R1
+// JMP exit
+// JMP 3(PC)
+func (p *Parser) asmJump(op int, a []addr.Addr) {
+       var target *addr.Addr
+       switch len(a) {
+       default:
+               p.errorf("jump must have one or two addresses")
+       case 1:
+               target = &a[0]
+       case 2:
+               if !a[0].Is(0) {
+                       p.errorf("two-address jump must have empty first address")
+               }
+               target = &a[1]
+       }
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               Lineno: int32(p.histLineNum),
+               As:     int16(op),
+               From:   p.arch.NoAddr,
+       }
+       switch {
+       case target.Is(addr.Register):
+               // JMP R1
+               prog.To = p.addrToAddr(target)
+       case target.Is(addr.Symbol):
+               // JMP exit
+               targetProg := p.labels[target.Symbol]
+               if targetProg == nil {
+                       p.toPatch = append(p.toPatch, Patch{prog, target.Symbol})
+               } else {
+                       p.branch(prog, targetProg)
+               }
+       case target.Is(addr.Register | addr.Indirect), target.Is(addr.Register | addr.Indirect | addr.Offset):
+               // JMP 4(AX)
+               if target.Register == arch.RPC {
+                       prog.To = obj.Addr{
+                               Type:   int16(p.arch.D_BRANCH),
+                               Index:  uint8(p.arch.D_NONE),
+                               Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in link, below.
+                       }
+               } else {
+                       prog.To = p.addrToAddr(target)
+               }
+       case target.Is(addr.Symbol | addr.Indirect | addr.Register):
+               // JMP main·morestack(SB)
+               if target.Register != arch.RSB {
+                       p.errorf("jmp to symbol must be SB-relative")
+               }
+               prog.To = obj.Addr{
+                       Type:   int16(p.arch.D_BRANCH),
+                       Sym:    obj.Linklookup(p.linkCtxt, target.Symbol, staticVersion(target)),
+                       Index:  uint8(p.arch.D_NONE),
+                       Offset: target.Offset,
+               }
+       default:
+               p.errorf("cannot assemble jump %+v", target)
+       }
+       p.append(prog, true)
+}
+
+func (p *Parser) patch() {
+       for _, patch := range p.toPatch {
+               targetProg := p.labels[patch.label]
+               if targetProg == nil {
+                       p.errorf("undefined label %s", patch.label)
+               } else {
+                       p.branch(patch.prog, targetProg)
+               }
+       }
+       p.toPatch = p.toPatch[:0]
+}
+
+func (p *Parser) branch(jmp, target *obj.Prog) {
+       jmp.To = obj.Addr{
+               Type:  int16(p.arch.D_BRANCH),
+               Index: uint8(p.arch.D_NONE),
+       }
+       jmp.To.U.Branch = target
+}
+
+// asmInstruction assembles an instruction.
+// MOVW R9, (R10)
+func (p *Parser) asmInstruction(op int, a []addr.Addr) {
+       prog := &obj.Prog{
+               Ctxt:   p.linkCtxt,
+               Lineno: int32(p.histLineNum),
+               As:     int16(op),
+       }
+       switch len(a) {
+       case 0:
+               prog.From = p.arch.NoAddr
+               prog.To = p.arch.NoAddr
+       case 1:
+               if p.arch.UnaryDestination[op] {
+                       prog.From = p.arch.NoAddr
+                       prog.To = p.addrToAddr(&a[0])
+               } else {
+                       prog.From = p.addrToAddr(&a[0])
+                       prog.To = p.arch.NoAddr
+               }
+       case 2:
+               prog.From = p.addrToAddr(&a[0])
+               prog.To = p.addrToAddr(&a[1])
+               // DX:AX as a register pair can only appear on the RHS.
+               // Bizarrely, to obj it's specified by setting index on the LHS.
+               // TODO: can we fix this?
+               if a[1].Has(addr.Register2) {
+                       if int(prog.From.Index) != p.arch.D_NONE {
+                               p.errorf("register pair operand on RHS must have register on LHS")
+                       }
+                       prog.From.Index = uint8(a[1].Register2)
+               }
+       case 3:
+               // CMPSD etc.; third operand is imm8, stored in offset, or a register.
+               prog.From = p.addrToAddr(&a[0])
+               prog.To = p.addrToAddr(&a[1])
+               switch {
+               case a[2].Is(addr.Offset):
+                       prog.To.Offset = a[2].Offset
+               case a[2].Is(addr.Register):
+                       // Strange reodering.
+                       prog.To = p.addrToAddr(&a[2])
+                       prog.From = p.addrToAddr(&a[1])
+                       if !a[0].IsImmediateConstant {
+                               p.errorf("expected $value for 1st operand")
+                       }
+                       prog.To.Offset = a[0].Offset
+               default:
+                       p.errorf("expected offset or register for 3rd operand")
+               }
+       default:
+               p.errorf("can't handle instruction with %d operands", len(a))
+       }
+       p.append(prog, true)
+}
diff --git a/src/cmd/asm/internal/asm/expr_test.go b/src/cmd/asm/internal/asm/expr_test.go
new file mode 100644 (file)
index 0000000..2ca6625
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asm
+
+import (
+       "cmd/asm/internal/lex"
+       "testing"
+       "text/scanner"
+)
+
+type exprTest struct {
+       input  string
+       output int64
+       atEOF  bool
+}
+
+var exprTests = []exprTest{
+       // Simple
+       {"0", 0, true},
+       {"3", 3, true},
+       {"070", 8 * 7, true},
+       {"0x0f", 15, true},
+       {"0xFF", 255, true},
+       {"9223372036854775807", 9223372036854775807, true}, // max int64
+       // Unary
+       {"-0", 0, true},
+       {"~0", -1, true},
+       {"~0*0", 0, true},
+       {"+3", 3, true},
+       {"-3", -3, true},
+       {"-9223372036854775808", -9223372036854775808, true}, // min int64
+       // Binary
+       {"3+4", 3 + 4, true},
+       {"3-4", 3 - 4, true},
+       {"2|5", 2 | 5, true},
+       {"3^4", 3 ^ 4, true},
+       {"3*4", 3 * 4, true},
+       {"14/4", 14 / 4, true},
+       {"3<<4", 3 << 4, true},
+       {"48>>3", 48 >> 3, true},
+       {"3&9", 3 & 9, true},
+       // General
+       {"3*2+3", 3*2 + 3, true},
+       {"3+2*3", 3 + 2*3, true},
+       {"3*(2+3)", 3 * (2 + 3), true},
+       {"3*-(2+3)", 3 * -(2 + 3), true},
+       {"3<<2+4", 3<<2 + 4, true},
+       {"3<<2+4", 3<<2 + 4, true},
+       {"3<<(2+4)", 3 << (2 + 4), true},
+       // Junk at EOF.
+       {"3 x", 3, false},
+}
+
+func TestExpr(t *testing.T) {
+       p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
+       for i, test := range exprTests {
+               p.start(lex.Tokenize(test.input))
+               result := int64(p.expr())
+               if result != test.output {
+                       t.Errorf("%d: %q evaluated to %d; expected %d", i, test.input, result, test.output)
+               }
+               tok := p.next()
+               if test.atEOF && tok.ScanToken != scanner.EOF {
+                       t.Errorf("%d: %q: at EOF got %s", i, test.input, tok)
+               } else if !test.atEOF && tok.ScanToken == scanner.EOF {
+                       t.Errorf("%d: %q: expected not EOF but at EOF", i, test.input)
+               }
+       }
+}
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
new file mode 100644 (file)
index 0000000..9420fc2
--- /dev/null
@@ -0,0 +1,550 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package asm implements the parser and instruction generator for the assembler.
+// TODO: Split apart?
+package asm
+
+import (
+       "fmt"
+       "log"
+       "os"
+       "strconv"
+       "text/scanner"
+
+       "cmd/asm/internal/addr"
+       "cmd/asm/internal/arch"
+       "cmd/asm/internal/lex"
+       "cmd/internal/obj"
+)
+
+type Parser struct {
+       lex           lex.TokenReader
+       lineNum       int   // Line number in source file.
+       histLineNum   int   // Cumulative line number across source files.
+       errorLine     int   // (Cumulative) line number of last error.
+       errorCount    int   // Number of errors.
+       pc            int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
+       input         []lex.Token
+       inputPos      int
+       pendingLabels []string // Labels to attach to next instruction.
+       labels        map[string]*obj.Prog
+       toPatch       []Patch
+       addr          []addr.Addr
+       arch          *arch.Arch
+       linkCtxt      *obj.Link
+       firstProg     *obj.Prog
+       lastProg      *obj.Prog
+       dataAddr      map[string]int64 // Most recent address for DATA for this symbol.
+}
+
+type Patch struct {
+       prog  *obj.Prog
+       label string
+}
+
+func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
+       return &Parser{
+               linkCtxt: ctxt,
+               arch:     ar,
+               lex:      lexer,
+               labels:   make(map[string]*obj.Prog),
+               dataAddr: make(map[string]int64),
+       }
+}
+
+func (p *Parser) errorf(format string, args ...interface{}) {
+       if p.histLineNum == p.errorLine {
+               // Only one error per line.
+               return
+       }
+       p.errorLine = p.histLineNum
+       // Put file and line information on head of message.
+       format = "%s:%d: " + format + "\n"
+       args = append([]interface{}{p.lex.File(), p.lineNum}, args...)
+       fmt.Fprintf(os.Stderr, format, args...)
+       p.errorCount++
+       if p.errorCount > 10 {
+               log.Fatal("too many errors")
+       }
+}
+
+func (p *Parser) Parse() (*obj.Prog, bool) {
+       for p.line() {
+       }
+       if p.errorCount > 0 {
+               return nil, false
+       }
+       p.patch()
+       return p.firstProg, true
+}
+
+// WORD [ arg {, arg} ] (';' | '\n')
+func (p *Parser) line() bool {
+       // Skip newlines.
+       var tok lex.ScanToken
+       for {
+               tok = p.lex.Next()
+               // We save the line number here so error messages from this instruction
+               // are labeled with this line. Otherwise we complain after we've absorbed
+               // the terminating newline and the line numbers are off by one in errors.
+               p.lineNum = p.lex.Line()
+               p.histLineNum = lex.HistLine()
+               switch tok {
+               case '\n', ';':
+                       continue
+               case scanner.EOF:
+                       return false
+               }
+               break
+       }
+       // First item must be an identifier.
+       if tok != scanner.Ident {
+               p.errorf("expected identifier, found %q", p.lex.Text())
+               return false // Might as well stop now.
+       }
+       word := p.lex.Text()
+       operands := make([][]lex.Token, 0, 3)
+       // Zero or more comma-separated operands, one per loop.
+       for tok != '\n' && tok != ';' {
+               // Process one operand.
+               items := make([]lex.Token, 0, 3)
+               for {
+                       tok = p.lex.Next()
+                       if tok == ':' && len(operands) == 0 && len(items) == 0 { // First token.
+                               p.pendingLabels = append(p.pendingLabels, word)
+                               return true
+                       }
+                       if tok == scanner.EOF {
+                               p.errorf("unexpected EOF")
+                               return false
+                       }
+                       if tok == '\n' || tok == ';' || tok == ',' {
+                               break
+                       }
+                       items = append(items, lex.Make(tok, p.lex.Text()))
+               }
+               if len(items) > 0 {
+                       operands = append(operands, items)
+               } else if len(operands) > 0 || tok == ',' {
+                       // Had a comma with nothing after.
+                       p.errorf("missing operand")
+               }
+       }
+       i := p.arch.Pseudos[word]
+       if i != 0 {
+               p.pseudo(i, word, operands)
+               return true
+       }
+       i = p.arch.Instructions[word]
+       if i != 0 {
+               p.instruction(i, word, operands)
+               return true
+       }
+       p.errorf("unrecognized instruction %s", word)
+       return true
+}
+
+func (p *Parser) instruction(op int, word string, operands [][]lex.Token) {
+       p.addr = p.addr[0:0]
+       for _, op := range operands {
+               p.addr = append(p.addr, p.address(op))
+       }
+       // Is it a jump? TODO
+       if word[0] == 'J' || word == "CALL" {
+               p.asmJump(op, p.addr)
+               return
+       }
+       p.asmInstruction(op, p.addr)
+}
+
+func (p *Parser) pseudo(op int, word string, operands [][]lex.Token) {
+       switch op {
+       case p.arch.ATEXT:
+               p.asmText(word, operands)
+       case p.arch.ADATA:
+               p.asmData(word, operands)
+       case p.arch.AGLOBL:
+               p.asmGlobl(word, operands)
+       case p.arch.APCDATA:
+               p.asmPCData(word, operands)
+       case p.arch.AFUNCDATA:
+               p.asmFuncData(word, operands)
+       default:
+               p.errorf("unimplemented: %s", word)
+       }
+}
+
+func (p *Parser) start(operand []lex.Token) {
+       p.input = operand
+       p.inputPos = 0
+}
+
+// address parses the operand into a link address structure.
+func (p *Parser) address(operand []lex.Token) addr.Addr {
+       p.start(operand)
+       addr := addr.Addr{}
+       p.operand(&addr)
+       return addr
+}
+
+// parse (R). The opening paren is known to be there.
+// The return value states whether it was a scaled mode.
+func (p *Parser) parenRegister(a *addr.Addr) bool {
+       p.next()
+       tok := p.next()
+       if tok.ScanToken != scanner.Ident {
+               p.errorf("expected register, got %s", tok)
+       }
+       r, present := p.arch.Registers[tok.String()]
+       if !present {
+               p.errorf("expected register, found %s", tok.String())
+       }
+       a.IsIndirect = true
+       scaled := p.peek() == '*'
+       if scaled {
+               // (R*2)
+               p.next()
+               tok := p.get(scanner.Int)
+               a.Scale = p.scale(tok.String())
+               a.Index = int16(r) // TODO: r should have type int16 but is uint8.
+       } else {
+               if a.HasRegister {
+                       p.errorf("multiple indirections")
+               }
+               a.HasRegister = true
+               a.Register = int16(r)
+       }
+       p.expect(')')
+       p.next()
+       return scaled
+}
+
+// scale converts a decimal string into a valid scale factor.
+func (p *Parser) scale(s string) int8 {
+       switch s {
+       case "1", "2", "4", "8":
+               return int8(s[0] - '0')
+       }
+       p.errorf("bad scale: %s", s)
+       return 0
+}
+
+// parse (R) or (R)(R*scale). The opening paren is known to be there.
+func (p *Parser) addressMode(a *addr.Addr) {
+       scaled := p.parenRegister(a)
+       if !scaled && p.peek() == '(' {
+               p.parenRegister(a)
+       }
+}
+
+// operand parses a general operand and stores the result in *a.
+func (p *Parser) operand(a *addr.Addr) bool {
+       if len(p.input) == 0 {
+               p.errorf("empty operand: cannot happen")
+               return false
+       }
+       switch p.peek() {
+       case '$':
+               p.next()
+               switch p.peek() {
+               case scanner.Ident:
+                       a.IsImmediateAddress = true
+                       p.operand(a) // TODO
+               case scanner.String:
+                       a.IsImmediateConstant = true
+                       a.HasString = true
+                       a.String = p.atos(p.next().String())
+               case scanner.Int, scanner.Float, '+', '-', '~', '(':
+                       a.IsImmediateConstant = true
+                       if p.have(scanner.Float) {
+                               a.HasFloat = true
+                               a.Float = p.floatExpr()
+                       } else {
+                               a.HasOffset = true
+                               a.Offset = int64(p.expr())
+                       }
+               default:
+                       p.errorf("illegal %s in immediate operand", p.next().String())
+               }
+       case '*':
+               p.next()
+               tok := p.next()
+               r, present := p.arch.Registers[tok.String()]
+               if !present {
+                       p.errorf("expected register; got %s", tok.String())
+               }
+               a.HasRegister = true
+               a.Register = int16(r)
+       case '(':
+               p.next()
+               if p.peek() == scanner.Ident {
+                       p.back()
+                       p.addressMode(a)
+                       break
+               }
+               p.back()
+               fallthrough
+       case '+', '-', '~', scanner.Int, scanner.Float:
+               if p.have(scanner.Float) {
+                       a.HasFloat = true
+                       a.Float = p.floatExpr()
+               } else {
+                       a.HasOffset = true
+                       a.Offset = int64(p.expr())
+               }
+               if p.peek() != scanner.EOF {
+                       p.expect('(')
+                       p.addressMode(a)
+               }
+       case scanner.Ident:
+               tok := p.next()
+               // Either R or (most general) ident<>+4(SB)(R*scale).
+               if r, present := p.arch.Registers[tok.String()]; present {
+                       a.HasRegister = true
+                       a.Register = int16(r)
+                       // Possibly register pair: DX:AX.
+                       if p.peek() == ':' {
+                               p.next()
+                               tok = p.get(scanner.Ident)
+                               a.HasRegister2 = true
+                               a.Register2 = int16(p.arch.Registers[tok.String()])
+                       }
+                       break
+               }
+               // Weirdness with statics: Might now have "<>".
+               if p.peek() == '<' {
+                       p.next()
+                       p.get('>')
+                       a.IsStatic = true
+               }
+               if p.peek() == '+' || p.peek() == '-' {
+                       a.HasOffset = true
+                       a.Offset = int64(p.expr())
+               }
+               a.Symbol = tok.String()
+               if p.peek() == scanner.EOF {
+                       break
+               }
+               // Expect (SB) or (FP)
+               p.expect('(')
+               p.parenRegister(a)
+               if a.Register != arch.RSB && a.Register != arch.RFP && a.Register != arch.RSP {
+                       p.errorf("expected SB, FP, or SP offset for %s", tok)
+               }
+               // Possibly have scaled register (CX*8).
+               if p.peek() != scanner.EOF {
+                       p.expect('(')
+                       p.addressMode(a)
+               }
+       default:
+               p.errorf("unexpected %s in operand", p.next())
+       }
+       p.expect(scanner.EOF)
+       return true
+}
+
+// Note: There are two changes in the expression handling here
+// compared to the old yacc/C implemenatations. Neither has
+// much practical consequence because the expressions we
+// see in assembly code are simple, but for the record:
+//
+// 1) Evaluation uses uint64; the old one used int64.
+// 2) Precedence uses Go rules not C rules.
+
+// expr = term | term ('+' | '-' | '|' | '^') term.
+func (p *Parser) expr() uint64 {
+       value := p.term()
+       for {
+               switch p.peek() {
+               case '+':
+                       p.next()
+                       value += p.term()
+               case '-':
+                       p.next()
+                       value -= p.term()
+               case '|':
+                       p.next()
+                       value |= p.term()
+               case '^':
+                       p.next()
+                       value ^= p.term()
+               default:
+                       return value
+               }
+       }
+}
+
+// floatExpr = fconst | '-' floatExpr | '+' floatExpr | '(' floatExpr ')'
+func (p *Parser) floatExpr() float64 {
+       tok := p.next()
+       switch tok.ScanToken {
+       case '(':
+               v := p.floatExpr()
+               if p.next().ScanToken != ')' {
+                       p.errorf("missing closing paren")
+               }
+               return v
+       case '+':
+               return +p.floatExpr()
+       case '-':
+               return -p.floatExpr()
+       case scanner.Float:
+               return p.atof(tok.String())
+       }
+       p.errorf("unexpected %s evaluating float expression", tok)
+       return 0
+}
+
+// term = factor | factor ('*' | '/' | '%' | '>>' | '<<' | '&') factor
+func (p *Parser) term() uint64 {
+       value := p.factor()
+       for {
+               switch p.peek() {
+               case '*':
+                       p.next()
+                       value *= p.factor()
+               case '/':
+                       p.next()
+                       if value&(1<<63) != 0 {
+                               p.errorf("divide with high bit set")
+                       }
+                       value /= p.factor()
+               case '%':
+                       p.next()
+                       value %= p.factor()
+               case lex.LSH:
+                       p.next()
+                       shift := p.factor()
+                       if int64(shift) < 0 {
+                               p.errorf("negative left shift %d", shift)
+                       }
+                       return value << shift
+               case lex.RSH:
+                       p.next()
+                       shift := p.term()
+                       if shift < 0 {
+                               p.errorf("negative right shift %d", shift)
+                       }
+                       if shift > 0 && value&(1<<63) != 0 {
+                               p.errorf("right shift with high bit set")
+                       }
+                       value >>= uint(shift)
+               case '&':
+                       p.next()
+                       value &= p.factor()
+               default:
+                       return value
+               }
+       }
+}
+
+// factor = const | '+' factor | '-' factor | '~' factor | '(' expr ')'
+func (p *Parser) factor() uint64 {
+       tok := p.next()
+       switch tok.ScanToken {
+       case scanner.Int:
+               return p.atoi(tok.String())
+       case '+':
+               return +p.factor()
+       case '-':
+               return -p.factor()
+       case '~':
+               return ^p.factor()
+       case '(':
+               v := p.expr()
+               if p.next().ScanToken != ')' {
+                       p.errorf("missing closing paren")
+               }
+               return v
+       }
+       p.errorf("unexpected %s evaluating expression", tok)
+       return 0
+}
+
+// positiveAtoi returns an int64 that must be >= 0.
+func (p *Parser) positiveAtoi(str string) int64 {
+       value, err := strconv.ParseInt(str, 0, 64)
+       if err != nil {
+               p.errorf("%s", err)
+       }
+       if value < 0 {
+               p.errorf("%s overflows int64", str)
+       }
+       return value
+}
+
+func (p *Parser) atoi(str string) uint64 {
+       value, err := strconv.ParseUint(str, 0, 64)
+       if err != nil {
+               p.errorf("%s", err)
+       }
+       return value
+}
+
+func (p *Parser) atof(str string) float64 {
+       value, err := strconv.ParseFloat(str, 64)
+       if err != nil {
+               p.errorf("%s", err)
+       }
+       return value
+}
+
+func (p *Parser) atos(str string) string {
+       value, err := strconv.Unquote(str)
+       if err != nil {
+               p.errorf("%s", err)
+       }
+       return value
+}
+
+// EOF represents the end of input.
+var EOF = lex.Make(scanner.EOF, "EOF")
+
+func (p *Parser) next() lex.Token {
+       if !p.more() {
+               return EOF
+       }
+       tok := p.input[p.inputPos]
+       p.inputPos++
+       return tok
+}
+
+func (p *Parser) back() {
+       p.inputPos--
+}
+
+func (p *Parser) peek() lex.ScanToken {
+       if p.more() {
+               return p.input[p.inputPos].ScanToken
+       }
+       return scanner.EOF
+}
+
+func (p *Parser) more() bool {
+       return p.inputPos < len(p.input)
+}
+
+// get verifies that the next item has the expected type and returns it.
+func (p *Parser) get(expected lex.ScanToken) lex.Token {
+       p.expect(expected)
+       return p.next()
+}
+
+// expect verifies that the next item has the expected type. It does not consume it.
+func (p *Parser) expect(expected lex.ScanToken) {
+       if p.peek() != expected {
+               p.errorf("expected %s, found %s", expected, p.next())
+       }
+}
+
+// have reports whether the remaining tokens contain the specified token.
+func (p *Parser) have(token lex.ScanToken) bool {
+       for i := p.inputPos; i < len(p.input); i++ {
+               if p.input[i].ScanToken == token {
+                       return true
+               }
+       }
+       return false
+}
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
new file mode 100644 (file)
index 0000000..df0049f
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package flags implements top-level flags and the usage message for the assembler.
+package flags
+
+import (
+       "flag"
+       "fmt"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+var (
+       Debug      = flag.Bool("debug", false, "dump instructions as they are parsed")
+       OutputFile = flag.String("o", "", "output file; default foo.6 for /a/b/c/foo.s on amd64")
+       PrintOut   = flag.Bool("S", false, "print assembly and machine code")
+       TrimPath   = flag.String("trimpath", "", "remove prefix from recorded source file paths (unused TODO)")
+)
+
+var (
+       D MultiFlag
+       I MultiFlag
+)
+
+func init() {
+       flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifer=value; can be set multiple times")
+       flag.Var(&I, "I", "include directory; can be set multiple times")
+}
+
+// MultiFlag allows setting a value multiple times to collect a list, as in -I=dir1 -I=dir2.
+type MultiFlag []string
+
+func (m *MultiFlag) String() string {
+       return fmt.Sprint(*m)
+}
+
+func (m *MultiFlag) Set(val string) error {
+       (*m) = append(*m, val)
+       return nil
+}
+
+func Usage() {
+       fmt.Fprintf(os.Stderr, "usage: asm [options] file.s\n")
+       fmt.Fprintf(os.Stderr, "Flags:\n")
+       flag.PrintDefaults()
+       os.Exit(2)
+}
+
+func Parse(theChar int) {
+       flag.Usage = Usage
+       flag.Parse()
+       if flag.NArg() != 1 {
+               flag.Usage()
+       }
+
+       // Flag refinement.
+       if *OutputFile == "" {
+               input := filepath.Base(flag.Arg(0))
+               if strings.HasSuffix(input, ".s") {
+                       input = input[:len(input)-2]
+               }
+               *OutputFile = fmt.Sprintf("%s.%c", input, theChar)
+       }
+}
diff --git a/src/cmd/asm/internal/lex/input.go b/src/cmd/asm/internal/lex/input.go
new file mode 100644 (file)
index 0000000..4c8abaf
--- /dev/null
@@ -0,0 +1,455 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lex
+
+import (
+       "fmt"
+       "os"
+       "path/filepath"
+       "strconv"
+       "strings"
+       "text/scanner"
+
+       "cmd/asm/internal/flags"
+       "cmd/internal/obj"
+)
+
+// Input is the main input: a stack of readers and some macro definitions.
+// It also handles #include processing (by pushing onto the input stack)
+// and parses and instantiates macro definitions.
+type Input struct {
+       Stack
+       includes        []string
+       beginningOfLine bool
+       ifdefStack      []bool
+       macros          map[string]*Macro
+       text            string // Text of last token returned by Next.
+       peek            bool
+       peekToken       ScanToken
+       peekText        string
+}
+
+// NewInput returns a
+func NewInput(name string) *Input {
+       return &Input{
+               // include directories: look in source dir, then -I directories.
+               includes:        append([]string{filepath.Dir(name)}, flags.I...),
+               beginningOfLine: true,
+               macros:          predefine(flags.D),
+       }
+}
+
+// predefine installs the macros set by the -D flag on the command line.
+func predefine(defines flags.MultiFlag) map[string]*Macro {
+       macros := make(map[string]*Macro)
+       for _, name := range defines {
+               value := "1"
+               i := strings.IndexRune(name, '=')
+               if i > 0 {
+                       name, value = name[:i], name[i+1:]
+               }
+               tokens := Tokenize(name)
+               if len(tokens) != 1 || tokens[0].ScanToken != scanner.Ident {
+                       fmt.Fprintf(os.Stderr, "asm: parsing -D: %q is not a valid identifier name\n", tokens[0])
+                       flags.Usage()
+               }
+               macros[name] = &Macro{
+                       name:   name,
+                       args:   nil,
+                       tokens: Tokenize(value),
+               }
+       }
+       return macros
+}
+
+func (in *Input) Error(args ...interface{}) {
+       fmt.Fprintf(os.Stderr, "%s:%d: %s", in.File(), in.Line(), fmt.Sprintln(args...))
+       os.Exit(1)
+}
+
+// expectText is like Error but adds "got XXX" where XXX is a quoted representation of the most recent token.
+func (in *Input) expectText(args ...interface{}) {
+       in.Error(append(args, "; got", strconv.Quote(in.Stack.Text()))...)
+}
+
+// enabled reports whether the input is enabled by an ifdef, or is at the top level.
+func (in *Input) enabled() bool {
+       return len(in.ifdefStack) == 0 || in.ifdefStack[len(in.ifdefStack)-1]
+}
+
+func (in *Input) expectNewline(directive string) {
+       tok := in.Stack.Next()
+       if tok != '\n' {
+               in.expectText("expected newline after", directive)
+       }
+}
+
+func (in *Input) Next() ScanToken {
+       if in.peek {
+               in.peek = false
+               tok := in.peekToken
+               in.text = in.peekText
+               return tok
+       }
+       // If we cannot generate a token after 100 tries, we're in trouble.
+       // The usual case is caught by Push, below, but be safe.
+       for i := 0; i < 100; i++ {
+               tok := in.Stack.Next()
+               switch tok {
+               case '#':
+                       if !in.beginningOfLine {
+                               in.Error("'#' must be first item on line")
+                       }
+                       in.beginningOfLine = in.hash()
+               case scanner.Ident:
+                       // Is it a macro name?
+                       name := in.Stack.Text()
+                       macro := in.macros[name]
+                       if macro != nil {
+                               in.invokeMacro(macro)
+                               continue
+                       }
+                       fallthrough
+               default:
+                       in.beginningOfLine = tok == '\n'
+                       if in.enabled() {
+                               in.text = in.Stack.Text()
+                               return tok
+                       }
+               }
+       }
+       in.Error("recursive macro invocation")
+       return 0
+}
+
+func (in *Input) Text() string {
+       return in.text
+}
+
+// hash processes a # preprocessor directive. It returns true iff it completes.
+func (in *Input) hash() bool {
+       // We have a '#'; it must be followed by a known word (define, include, etc.).
+       tok := in.Stack.Next()
+       if tok != scanner.Ident {
+               in.expectText("expected identifier after '#'")
+       }
+       if !in.enabled() {
+               // Can only start including again if we are at #else or #endif.
+               // We let #line through because it might affect errors.
+               switch in.Stack.Text() {
+               case "else", "endif", "line":
+                       // Press on.
+               default:
+                       return false
+               }
+       }
+       switch in.Stack.Text() {
+       case "define":
+               in.define()
+       case "else":
+               in.else_()
+       case "endif":
+               in.endif()
+       case "ifdef":
+               in.ifdef(true)
+       case "ifndef":
+               in.ifdef(false)
+       case "include":
+               in.include()
+       case "line":
+               in.line()
+       case "undef":
+               in.undef()
+       default:
+               in.Error("unexpected token after '#':", in.Stack.Text())
+       }
+       return true
+}
+
+// macroName returns the name for the macro being referenced.
+func (in *Input) macroName() string {
+       // We use the Stack's input method; no macro processing at this stage.
+       tok := in.Stack.Next()
+       if tok != scanner.Ident {
+               in.expectText("expected identifier after # directive")
+       }
+       // Name is alphanumeric by definition.
+       return in.Stack.Text()
+}
+
+// #define processing.
+func (in *Input) define() {
+       name := in.macroName()
+       args, tokens := in.macroDefinition(name)
+       in.defineMacro(name, args, tokens)
+}
+
+// defineMacro stores the macro definition in the Input.
+func (in *Input) defineMacro(name string, args []string, tokens []Token) {
+       if in.macros[name] != nil {
+               in.Error("redefinition of macro:", name)
+       }
+       in.macros[name] = &Macro{
+               name:   name,
+               args:   args,
+               tokens: tokens,
+       }
+}
+
+// macroDefinition returns the list of formals and the tokens of the definition.
+// The argument list is nil for no parens on the definition; otherwise a list of
+// formal argument names.
+func (in *Input) macroDefinition(name string) ([]string, []Token) {
+       tok := in.Stack.Next()
+       if tok == '\n' || tok == scanner.EOF {
+               in.Error("no definition for macro:", name)
+       }
+       var args []string
+       if tok == '(' {
+               // Macro has arguments. Scan list of formals.
+               acceptArg := true
+               args = []string{} // Zero length but not nil.
+       Loop:
+               for {
+                       tok = in.Stack.Next()
+                       switch tok {
+                       case ')':
+                               tok = in.Stack.Next() // First token of macro definition.
+                               break Loop
+                       case ',':
+                               if acceptArg {
+                                       in.Error("bad syntax in definition for macro:", name)
+                               }
+                               acceptArg = true
+                       case scanner.Ident:
+                               if !acceptArg {
+                                       in.Error("bad syntax in definition for macro:", name)
+                               }
+                               arg := in.Stack.Text()
+                               if i := lookup(args, arg); i >= 0 {
+                                       in.Error("duplicate argument", arg, "in definition for macro:", name)
+                               }
+                               args = append(args, arg)
+                               acceptArg = false
+                       default:
+                               in.Error("bad definition for macro:", name)
+                       }
+               }
+       }
+       var tokens []Token
+       // Scan to newline. Backslashes escape newlines.
+       for tok != '\n' {
+               if tok == '\\' {
+                       tok = in.Stack.Next()
+                       if tok != '\n' && tok != '\\' {
+                               in.Error(`can only escape \ or \n in definition for macro:`, name)
+                       }
+               }
+               tokens = append(tokens, Make(tok, in.Stack.Text()))
+               tok = in.Stack.Next()
+       }
+       return args, tokens
+}
+
+func lookup(args []string, arg string) int {
+       for i, a := range args {
+               if a == arg {
+                       return i
+               }
+       }
+       return -1
+}
+
+// invokeMacro pushes onto the input Stack a Slice that holds the macro definition with the actual
+// parameters substituted for the formals.
+// Invoking a macro does not touch the PC/line history.
+func (in *Input) invokeMacro(macro *Macro) {
+       // If the macro has no arguments, just substitute the text.
+       if macro.args == nil {
+               in.Push(NewSlice(in.File(), in.Line(), macro.tokens))
+               return
+       }
+       tok := in.Stack.Next()
+       if tok != '(' {
+               // If the macro has arguments but is invoked without them, all we push is the macro name.
+               // First, put back the token.
+               in.peekToken = tok
+               in.peekText = in.text
+               in.peek = true
+               in.Push(NewSlice(in.File(), in.Line(), []Token{Make(macroName, macro.name)}))
+               return
+       }
+       actuals := in.argsFor(macro)
+       var tokens []Token
+       for _, tok := range macro.tokens {
+               if tok.ScanToken != scanner.Ident {
+                       tokens = append(tokens, tok)
+                       continue
+               }
+               substitution := actuals[tok.text]
+               if substitution == nil {
+                       tokens = append(tokens, tok)
+                       continue
+               }
+               tokens = append(tokens, substitution...)
+       }
+       in.Push(NewSlice(in.File(), in.Line(), tokens))
+}
+
+// argsFor returns a map from formal name to actual value for this argumented macro invocation.
+// The opening parenthesis has been absorbed.
+func (in *Input) argsFor(macro *Macro) map[string][]Token {
+       var args [][]Token
+       // One macro argument per iteration. Collect them all and check counts afterwards.
+       for argNum := 0; ; argNum++ {
+               tokens, tok := in.collectArgument(macro)
+               args = append(args, tokens)
+               if tok == ')' {
+                       break
+               }
+       }
+       // Zero-argument macros are tricky.
+       if len(macro.args) == 0 && len(args) == 1 && args[0] == nil {
+               args = nil
+       } else if len(args) != len(macro.args) {
+               in.Error("wrong arg count for macro", macro.name)
+       }
+       argMap := make(map[string][]Token)
+       for i, arg := range args {
+               argMap[macro.args[i]] = arg
+       }
+       return argMap
+}
+
+// collectArgument returns the actual tokens for a single argument of a macro.
+// It also returns the token that terminated the argument, which will always
+// be either ',' or ')'. The starting '(' has been scanned.
+func (in *Input) collectArgument(macro *Macro) ([]Token, ScanToken) {
+       nesting := 0
+       var tokens []Token
+       for {
+               tok := in.Stack.Next()
+               if tok == scanner.EOF || tok == '\n' {
+                       in.Error("unterminated arg list invoking macro:", macro.name)
+               }
+               if nesting == 0 && (tok == ')' || tok == ',') {
+                       return tokens, tok
+               }
+               if tok == '(' {
+                       nesting++
+               }
+               if tok == ')' {
+                       nesting--
+               }
+               tokens = append(tokens, Make(tok, in.Stack.Text()))
+       }
+}
+
+// #ifdef and #ifndef processing.
+func (in *Input) ifdef(truth bool) {
+       name := in.macroName()
+       in.expectNewline("#if[n]def")
+       if _, defined := in.macros[name]; !defined {
+               truth = !truth
+       }
+       in.ifdefStack = append(in.ifdefStack, truth)
+}
+
+// #else processing
+func (in *Input) else_() {
+       in.expectNewline("#else")
+       if len(in.ifdefStack) == 0 {
+               in.Error("unmatched #else")
+       }
+       in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1]
+}
+
+// #endif processing.
+func (in *Input) endif() {
+       in.expectNewline("#endif")
+       if len(in.ifdefStack) == 0 {
+               in.Error("unmatched #endif")
+       }
+       in.ifdefStack = in.ifdefStack[:len(in.ifdefStack)-1]
+}
+
+// #include processing.
+func (in *Input) include() {
+       // Find and parse string.
+       tok := in.Stack.Next()
+       if tok != scanner.String {
+               in.expectText("expected string after #include")
+       }
+       name, err := strconv.Unquote(in.Stack.Text())
+       if err != nil {
+               in.Error("unquoting include file name: ", err)
+       }
+       in.expectNewline("#include")
+       // Push tokenizer for file onto stack.
+       fd, err := os.Open(name)
+       if err != nil {
+               for _, dir := range in.includes {
+                       fd, err = os.Open(filepath.Join(dir, name))
+                       if err == nil {
+                               break
+                       }
+               }
+               if err != nil {
+                       in.Error("#include:", err)
+               }
+       }
+       in.Push(NewTokenizer(name, fd, fd))
+}
+
+// #line processing.
+func (in *Input) line() {
+       // Only need to handle Plan 9 format: #line 337 "filename"
+       tok := in.Stack.Next()
+       if tok != scanner.Int {
+               in.expectText("expected line number after #line")
+       }
+       line, err := strconv.Atoi(in.Stack.Text())
+       if err != nil {
+               in.Error("error parsing #line (cannot happen):", err)
+       }
+       tok = in.Stack.Next()
+       if tok != scanner.String {
+               in.expectText("expected file name in #line")
+       }
+       file, err := strconv.Unquote(in.Stack.Text())
+       if err != nil {
+               in.Error("unquoting #line file name: ", err)
+       }
+       tok = in.Stack.Next()
+       if tok != '\n' {
+               in.Error("unexpected token at end of #line: ", tok)
+       }
+       obj.Linklinehist(linkCtxt, histLine, file, line)
+       in.Stack.SetPos(line, file)
+}
+
+// #undef processing
+func (in *Input) undef() {
+       name := in.macroName()
+       if in.macros[name] == nil {
+               in.Error("#undef for undefined macro:", name)
+       }
+       // Newline must be next.
+       tok := in.Stack.Next()
+       if tok != '\n' {
+               in.Error("syntax error in #undef for macro:", name)
+       }
+       delete(in.macros, name)
+}
+
+func (in *Input) Push(r TokenReader) {
+       if len(in.tr) > 100 {
+               in.Error("input recursion")
+       }
+       in.Stack.Push(r)
+}
+
+func (in *Input) Close() {
+}
diff --git a/src/cmd/asm/internal/lex/lex.go b/src/cmd/asm/internal/lex/lex.go
new file mode 100644 (file)
index 0000000..bf45ae7
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package lex implements lexical analysis for the assembler.
+package lex
+
+import (
+       "fmt"
+       "log"
+       "os"
+       "strings"
+       "text/scanner"
+
+       "cmd/internal/obj"
+)
+
+// A ScanToken represents an input item. It is a simple wrapping of rune, as
+// returned by text/scanner.Scanner, plus a couple of extra values.
+type ScanToken rune
+
+const (
+       // Asm defines some two-character lexemes. We make up
+       // a rune/ScanToken value for them - ugly but simple.
+       LSH       ScanToken = -1000 - iota // << Left shift.
+       RSH                                // >> Logical right shift.
+       ARR                                // -> Used on ARM for shift type 3, arithmetic right shift.
+       ROT                                // @> Used on ARM for shift type 4, rotate right.
+       macroName                          // name of macro that should not be expanded
+)
+
+func (t ScanToken) String() string {
+       switch t {
+       case scanner.EOF:
+               return "EOF"
+       case scanner.Ident:
+               return "identifier"
+       case scanner.Int:
+               return "integer constant"
+       case scanner.Float:
+               return "float constant"
+       case scanner.Char:
+               return "rune constant"
+       case scanner.String:
+               return "string constant"
+       case scanner.RawString:
+               return "raw string constant"
+       case scanner.Comment:
+               return "comment"
+       default:
+               return fmt.Sprintf("%q", rune(t))
+       }
+}
+
+var (
+       // It might be nice if these weren't global.
+       linkCtxt *obj.Link     // The link context for all instructions.
+       histLine int       = 1 // The cumulative count of lines processed.
+)
+
+// HistLine reports the cumulative source line number of the token,
+// for use in the Prog structure for the linker. (It's always handling the
+// instruction from the current lex line.)
+func HistLine() int {
+       return histLine
+}
+
+// NewLexer returns a lexer for the named file and the given link context.
+func NewLexer(name string, ctxt *obj.Link) TokenReader {
+       linkCtxt = ctxt
+       input := NewInput(name)
+       fd, err := os.Open(name)
+       if err != nil {
+               log.Fatalf("asm: %s\n", err)
+       }
+       input.Push(NewTokenizer(name, fd, fd))
+       return input
+}
+
+// The other files in this directory each contain an implementation of TokenReader.
+
+// A TokenReader is like a reader, but returns lex tokens of type Token. It also can tell you what
+// the text of the most recently returned token is, and where it was found.
+// The underlying scanner elides all spaces except newline, so the input looks like a  stream of
+// Tokens; original spacing is lost but we don't need it.
+type TokenReader interface {
+       // Next returns the next token.
+       Next() ScanToken
+       // The following methods all refer to the most recent token returned by Next.
+       // Text returns the original string representation of the token.
+       Text() string
+       // File reports the source file name of the token.
+       File() string
+       // Line reports the source line number of the token.
+       Line() int
+       // SetPos sets the file and line number.
+       SetPos(line int, file string)
+       // Close does any teardown required.
+       Close()
+}
+
+// A Token is a scan token plus its string value.
+// A macro is stored as a sequence of Tokens with spaces stripped.
+type Token struct {
+       ScanToken
+       text string
+}
+
+// Make returns a Token with the given rune (ScanToken) and text representation.
+func Make(token ScanToken, text string) Token {
+       // If the symbol starts with center dot, as in Â·x, rewrite it as ""·x
+       if token == scanner.Ident && strings.HasPrefix(text, "\u00B7") {
+               text = `""` + text
+       }
+       // Substitute the substitutes for . and /.
+       text = strings.Replace(text, "\u00B7", ".", -1)
+       text = strings.Replace(text, "\u2215", "/", -1)
+       return Token{ScanToken: token, text: text}
+}
+
+func (l Token) String() string {
+       return l.text
+}
+
+// A Macro represents the definition of a #defined macro.
+type Macro struct {
+       name   string   // The #define name.
+       args   []string // Formal arguments.
+       tokens []Token  // Body of macro.
+}
+
+// Tokenize turns a string into a list of Tokens; used to parse the -D flag and in tests.
+func Tokenize(str string) []Token {
+       t := NewTokenizer("command line", strings.NewReader(str), nil)
+       var tokens []Token
+       for {
+               tok := t.Next()
+               if tok == scanner.EOF {
+                       break
+               }
+               tokens = append(tokens, Make(tok, t.Text()))
+       }
+       return tokens
+}
diff --git a/src/cmd/asm/internal/lex/lex_test.go b/src/cmd/asm/internal/lex/lex_test.go
new file mode 100644 (file)
index 0000000..64f6784
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lex
+
+import (
+       "bytes"
+       "strings"
+       "testing"
+       "text/scanner"
+)
+
+type lexTest struct {
+       name   string
+       input  string
+       output string
+}
+
+var lexTests = []lexTest{
+       {
+               "empty",
+               "",
+               "",
+       },
+       {
+               "simple",
+               "1 (a)",
+               "1.(.a.)",
+       },
+       {
+               "simple define",
+               lines(
+                       "#define A 1234",
+                       "A",
+               ),
+               "1234.\n",
+       },
+       {
+               "macro without arguments",
+               "#define A() 1234\n" + "A()\n",
+               "1234.\n",
+       },
+       {
+               "macro with arguments",
+               "#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
+               "1.+.3.+.2.\n",
+       },
+       {
+               "argumented macro invoked without arguments",
+               lines(
+                       "#define X() foo ",
+                       "X()",
+                       "X",
+               ),
+               "foo.\n.X.\n",
+       },
+       {
+               "multiline macro without arguments",
+               lines(
+                       "#define A 1\\",
+                       "\t2\\",
+                       "\t3",
+                       "before",
+                       "A",
+                       "after",
+               ),
+               "before.\n.1.\n.2.\n.3.\n.after.\n",
+       },
+       {
+               "multiline macro with arguments",
+               lines(
+                       "#define A(a, b, c) a\\",
+                       "\tb\\",
+                       "\tc",
+                       "before",
+                       "A(1, 2, 3)",
+                       "after",
+               ),
+               "before.\n.1.\n.2.\n.3.\n.after.\n",
+       },
+       {
+               "LOAD macro",
+               lines(
+                       "#define LOAD(off, reg) \\",
+                       "\tMOVBLZX      (off*4)(R12),   reg \\",
+                       "\tADDB reg,            DX",
+                       "",
+                       "LOAD(8, AX)",
+               ),
+               "\n.\n.MOVBLZX.(.8.*.4.).(.R12.).,.AX.\n.ADDB.AX.,.DX.\n",
+       },
+       {
+               "nested multiline macro",
+               lines(
+                       "#define KEYROUND(xmm, load, off, r1, r2, index) \\",
+                       "\tMOVBLZX      (BP)(DX*4),     R8 \\",
+                       "\tload((off+1), r2) \\",
+                       "\tMOVB R8,             (off*4)(R12) \\",
+                       "\tPINSRW       $index, (BP)(R8*4), xmm",
+                       "#define LOAD(off, reg) \\",
+                       "\tMOVBLZX      (off*4)(R12),   reg \\",
+                       "\tADDB reg,            DX",
+                       "KEYROUND(X0, LOAD, 8, AX, BX, 0)",
+               ),
+               "\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n",
+       },
+}
+
+func TestLex(t *testing.T) {
+       for _, test := range lexTests {
+               input := NewInput(test.name)
+               input.Push(NewTokenizer(test.name, strings.NewReader(test.input), nil))
+               result := drain(input)
+               if result != test.output {
+                       t.Errorf("%s: got %q expected %q", test.name, result, test.output)
+               }
+       }
+}
+
+// lines joins the arguments together as complete lines.
+func lines(a ...string) string {
+       return strings.Join(a, "\n") + "\n"
+}
+
+// drain returns a single string representing the processed input tokens.
+func drain(input *Input) string {
+       var buf bytes.Buffer
+       for {
+               tok := input.Next()
+               if tok == scanner.EOF {
+                       return buf.String()
+               }
+               if buf.Len() > 0 {
+                       buf.WriteByte('.')
+               }
+               buf.WriteString(input.Text())
+       }
+}
diff --git a/src/cmd/asm/internal/lex/slice.go b/src/cmd/asm/internal/lex/slice.go
new file mode 100644 (file)
index 0000000..6ac72f4
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lex
+
+import "text/scanner"
+
+// A Slice reads from a slice of Tokens.
+type Slice struct {
+       tokens   []Token
+       fileName string
+       line     int
+       pos      int
+}
+
+func NewSlice(fileName string, line int, tokens []Token) *Slice {
+       return &Slice{
+               tokens:   tokens,
+               fileName: fileName,
+               line:     line,
+               pos:      -1, // Next will advance to zero.
+       }
+}
+
+func (s *Slice) Next() ScanToken {
+       s.pos++
+       if s.pos >= len(s.tokens) {
+               return scanner.EOF
+       }
+       return s.tokens[s.pos].ScanToken
+}
+
+func (s *Slice) Text() string {
+       return s.tokens[s.pos].text
+}
+
+func (s *Slice) File() string {
+       return s.fileName
+}
+
+func (s *Slice) Line() int {
+       return s.line
+}
+
+func (s *Slice) SetPos(line int, file string) {
+       // Cannot happen because we only have slices of already-scanned
+       // text, but be prepared.
+       s.line = line
+       s.fileName = file
+}
+
+func (s *Slice) Close() {
+}
diff --git a/src/cmd/asm/internal/lex/stack.go b/src/cmd/asm/internal/lex/stack.go
new file mode 100644 (file)
index 0000000..5e3b7be
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lex
+
+import "text/scanner"
+
+// A Stack is a stack of TokenReaders. As the top TokenReader hits EOF,
+// it resumes reading the next one down.
+type Stack struct {
+       tr []TokenReader
+}
+
+// Push adds tr to the top (end) of the input stack. (Popping happens automatically.)
+func (s *Stack) Push(tr TokenReader) {
+       s.tr = append(s.tr, tr)
+}
+
+func (s *Stack) Next() ScanToken {
+       tos := s.tr[len(s.tr)-1]
+       tok := tos.Next()
+       for tok == scanner.EOF && len(s.tr) > 1 {
+               tos.Close()
+               /*
+                       // If it's not a macro (a Slice at this point), pop the line history stack and close the file descriptor.
+                       if _, isMacro := tos.(*Slice); !isMacro {
+                               // TODO: close file descriptor.
+                               obj.Linklinehist(linkCtxt, histLine, "<pop>", 0)
+                       }
+               */
+               // Pop the topmost item from the stack and resume with the next one down.
+               s.tr = s.tr[:len(s.tr)-1]
+               tok = s.Next()
+       }
+       return tok
+}
+
+func (s *Stack) Text() string {
+       return s.tr[len(s.tr)-1].Text()
+}
+
+func (s *Stack) File() string {
+       return s.tr[len(s.tr)-1].File()
+}
+
+func (s *Stack) Line() int {
+       return s.tr[len(s.tr)-1].Line()
+}
+
+func (s *Stack) SetPos(line int, file string) {
+       s.tr[len(s.tr)-1].SetPos(line, file)
+}
+
+func (s *Stack) Close() { // Unused.
+}
diff --git a/src/cmd/asm/internal/lex/tokenizer.go b/src/cmd/asm/internal/lex/tokenizer.go
new file mode 100644 (file)
index 0000000..24a7247
--- /dev/null
@@ -0,0 +1,150 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package lex
+
+import (
+       "io"
+       "os"
+       "strings"
+       "text/scanner"
+       "unicode"
+
+       "cmd/internal/obj"
+)
+
+// A Tokenizer is a simple wrapping of text/scanner.Scanner, configured
+// for our purposes and made a TokenReader. It forms the lowest level,
+// turning text from readers into tokens.
+type Tokenizer struct {
+       tok      ScanToken
+       s        *scanner.Scanner
+       line     int
+       fileName string
+       file     *os.File // If non-nil, file descriptor to close.
+}
+
+func NewTokenizer(name string, r io.Reader, file *os.File) *Tokenizer {
+       var s scanner.Scanner
+       s.Init(r)
+       // Newline is like a semicolon; other space characters are fine.
+       s.Whitespace = 1<<'\t' | 1<<'\r' | 1<<' '
+       // Don't skip comments: we need to count newlines.
+       s.Mode = scanner.ScanChars |
+               scanner.ScanFloats |
+               scanner.ScanIdents |
+               scanner.ScanInts |
+               scanner.ScanStrings |
+               scanner.ScanComments
+       s.Position.Filename = name
+       s.IsIdentRune = isIdentRune
+       if file != nil {
+               obj.Linklinehist(linkCtxt, histLine, name, 0)
+       }
+       return &Tokenizer{
+               s:        &s,
+               line:     1,
+               fileName: name,
+               file:     file,
+       }
+}
+
+// We want center dot (·) and division slash (∕) to work as identifier characters.
+func isIdentRune(ch rune, i int) bool {
+       if unicode.IsLetter(ch) {
+               return true
+       }
+       switch ch {
+       case '_': // Underscore; traditional.
+               return true
+       case '\u00B7': // Represents the period in runtime.exit. U+00B7 '·' middle dot
+               return true
+       case '\u2215': // Represents the slash in runtime/debug.setGCPercent. U+2215 '∕' division slash
+               return true
+       }
+       // Digits are OK only after the first character.
+       return i > 0 && unicode.IsDigit(ch)
+}
+
+func (t *Tokenizer) Text() string {
+       switch t.tok {
+       case LSH:
+               return "<<"
+       case RSH:
+               return ">>"
+       case ARR:
+               return "->"
+       case ROT:
+               return "@>"
+       }
+       return t.s.TokenText()
+}
+
+func (t *Tokenizer) File() string {
+       return t.fileName
+}
+
+func (t *Tokenizer) Line() int {
+       return t.line
+}
+
+func (t *Tokenizer) SetPos(line int, file string) {
+       t.line = line
+       t.fileName = file
+}
+
+func (t *Tokenizer) Next() ScanToken {
+       s := t.s
+       for {
+               t.tok = ScanToken(s.Scan())
+               if t.tok != scanner.Comment {
+                       break
+               }
+               length := strings.Count(s.TokenText(), "\n")
+               t.line += length
+               histLine += length
+               // TODO: If we ever have //go: comments in assembly, will need to keep them here.
+               // For now, just discard all comments.
+       }
+       switch t.tok {
+       case '\n':
+               if t.file != nil {
+                       histLine++
+               }
+               t.line++
+       case '-':
+               if s.Peek() == '>' {
+                       s.Next()
+                       t.tok = ARR
+                       return ARR
+               }
+       case '@':
+               if s.Peek() == '>' {
+                       s.Next()
+                       t.tok = ROT
+                       return ROT
+               }
+       case '<':
+               if s.Peek() == '<' {
+                       s.Next()
+                       t.tok = LSH
+                       return LSH
+               }
+       case '>':
+               if s.Peek() == '>' {
+                       s.Next()
+                       t.tok = RSH
+                       return RSH
+               }
+       }
+       return t.tok
+}
+
+func (t *Tokenizer) Close() {
+       if t.file != nil {
+               t.file.Close()
+               // It's an open file, so pop the line history.
+               obj.Linklinehist(linkCtxt, histLine, "<pop>", 0)
+       }
+}
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
new file mode 100644 (file)
index 0000000..31d5b95
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "flag"
+       "fmt"
+       "log"
+       "os"
+
+       "cmd/asm/internal/arch"
+       "cmd/asm/internal/asm"
+       "cmd/asm/internal/flags"
+       "cmd/asm/internal/lex"
+
+       "cmd/internal/obj"
+)
+
+func main() {
+       log.SetFlags(0)
+       log.SetPrefix("asm: ")
+
+       GOARCH := obj.Getgoarch()
+
+       architecture := arch.Set(GOARCH)
+       if architecture == nil {
+               log.Fatalf("asm: unrecognized architecture %s", GOARCH)
+       }
+
+       flags.Parse(architecture.Thechar)
+
+       // Create object file, write header.
+       fd, err := os.Create(*flags.OutputFile)
+       if err != nil {
+               log.Fatal(err)
+       }
+       ctxt := obj.Linknew(architecture.LinkArch)
+       if *flags.PrintOut {
+               ctxt.Debugasm = 1
+       }
+       ctxt.Bso = obj.Binitw(os.Stdout)
+       defer obj.Bflush(ctxt.Bso)
+       ctxt.Diag = log.Fatalf
+       output := obj.Binitw(fd)
+       fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
+       fmt.Fprintf(output, "!\n")
+
+       lexer := lex.NewLexer(flag.Arg(0), ctxt)
+       parser := asm.NewParser(ctxt, architecture, lexer)
+       pList := obj.Linknewplist(ctxt)
+       var ok bool
+       pList.Firstpc, ok = parser.Parse()
+       if !ok {
+               log.Fatalf("asm: assembly of %s failed", flag.Arg(0))
+               os.Exit(1)
+       }
+       obj.Writeobjdirect(ctxt, output)
+       obj.Bflush(output)
+}
index f586aaa20e670994081be7dfd388ba92b8f3aec5..4749273eba88d20dc97545dd0006831a149d6c55 100644 (file)
@@ -572,6 +572,8 @@ getc(void)
        c = peekc;
        if(c != IGN) {
                peekc = IGN;
+               if(c == '\n')
+                       lineno++;
                return c;
        }
        c = GETC();
@@ -633,7 +635,7 @@ loop:
                                return l;
                        }
                }
-               peekc = c;
+               unget(c);
                return l;
        }
        switch(c)
index e36df51f5dce1afcddebc0c3f652c82c55ea2f82..152655b5086fb51c3eb5219ea43656dbbdef69ba 100644 (file)
@@ -37,6 +37,7 @@ var (
        oldgoarch        string
        oldgochar        string
        slash            string
+       exe              string
        defaultcc        string
        defaultcflags    string
        defaultldflags   string
@@ -356,6 +357,7 @@ var oldtool = []string{
 // not be in release branches.
 var unreleased = []string{
        "src/cmd/link",
+       "src/cmd/objwriter",
        "src/debug/goobj",
        "src/old",
 }
@@ -626,13 +628,20 @@ func install(dir string) {
                ldargs = splitfields(defaultldflags)
        }
 
-       islib := strings.HasPrefix(dir, "lib") || dir == "cmd/gc"
-       ispkg := !islib && !strings.HasPrefix(dir, "cmd/")
-       isgo := ispkg || dir == "cmd/go" || dir == "cmd/cgo"
+       isgo := true
+       ispkg := !strings.HasPrefix(dir, "cmd/") || strings.HasPrefix(dir, "cmd/internal/")
+       islib := false
 
-       exe := ""
-       if gohostos == "windows" {
-               exe = ".exe"
+       // Legacy C exceptions.
+       switch dir {
+       case "lib9", "libbio", "liblink", "cmd/gc":
+               islib = true
+               isgo = false
+       case "cmd/5a", "cmd/5g", "cmd/5l",
+               "cmd/6a", "cmd/6g", "cmd/6l",
+               "cmd/8a", "cmd/8g", "cmd/8l",
+               "cmd/9a", "cmd/9g", "cmd/9l":
+               isgo = false
        }
 
        // Start final link command line.
@@ -902,6 +911,8 @@ func install(dir string) {
                                compile = append(compile,
                                        "-D", fmt.Sprintf("GOOS=%q", goos),
                                        "-D", fmt.Sprintf("GOARCH=%q", goarch),
+                                       "-D", fmt.Sprintf("GOHOSTOS=%q", gohostos),
+                                       "-D", fmt.Sprintf("GOHOSTARCH=%q", gohostarch),
                                        "-D", fmt.Sprintf("GOROOT=%q", goroot_final),
                                        "-D", fmt.Sprintf("GOVERSION=%q", goversion),
                                        "-D", fmt.Sprintf("GOARM=%q", goarm),
@@ -1097,7 +1108,10 @@ func dopack(dst, src string, extra []string) {
 }
 
 // buildorder records the order of builds for the 'go bootstrap' command.
+// The Go packages and commands must be in dependency order,
+// maintained by hand, but the order doesn't change often.
 var buildorder = []string{
+       // Legacy C programs.
        "lib9",
        "libbio",
        "liblink",
@@ -1107,10 +1121,7 @@ var buildorder = []string{
        "cmd/%sa",
        "cmd/%sg",
 
-       // The dependency order here was copied from a buildscript
-       // back when there were build scripts.  Will have to
-       // be maintained by hand, but shouldn't change very
-       // often.
+       // Go libraries and programs for bootstrap.
        "runtime",
        "errors",
        "sync/atomic",
@@ -1133,6 +1144,7 @@ var buildorder = []string{
        "reflect",
        "fmt",
        "encoding",
+       "encoding/binary",
        "encoding/json",
        "flag",
        "path/filepath",
@@ -1152,6 +1164,12 @@ var buildorder = []string{
        "text/template",
        "go/doc",
        "go/build",
+       "cmd/internal/obj",
+       "cmd/internal/obj/arm",
+       "cmd/internal/obj/i386",
+       "cmd/internal/obj/ppc64",
+       "cmd/internal/obj/x86",
+       "cmd/objwriter",
        "cmd/go",
 }
 
@@ -1347,6 +1365,8 @@ func cmdbootstrap() {
 
        setup()
 
+       bootstrapBuildTools()
+
        // For the main bootstrap, building for host os/arch.
        oldgoos = goos
        oldgoarch = goarch
@@ -1359,6 +1379,31 @@ func cmdbootstrap() {
        os.Setenv("GOARCH", goarch)
        os.Setenv("GOOS", goos)
 
+       // TODO(rsc): Enable when appropriate.
+       // This step is only needed if we believe that the Go compiler built from Go 1.4
+       // will produce different object files than the Go compiler built from itself.
+       // In the absence of bugs, that should not happen.
+       // And if there are bugs, they're more likely in the current development tree
+       // than in a standard release like Go 1.4, so don't do this rebuild by default.
+       if false {
+               xprintf("##### Building Go toolchain using itself.\n")
+               for _, pattern := range buildorder {
+                       if pattern == "cmd/go" {
+                               break
+                       }
+                       dir := pattern
+                       if strings.Contains(pattern, "%s") {
+                               dir = fmt.Sprintf(pattern, gohostchar)
+                       }
+                       install(dir)
+                       if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
+                               install(fmt.Sprintf(pattern, oldgochar))
+                       }
+               }
+               xprintf("\n")
+       }
+
+       xprintf("##### Building compilers and go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
        for _, pattern := range buildorder {
                dir := pattern
                if strings.Contains(pattern, "%s") {
index d659234578ff0be6009b3c8e34b8be89f092215e..ff2a489b5594642d26587d09047d7999829ec6fb 100644 (file)
@@ -32,3 +32,31 @@ func mkzversion(dir, file string) {
 
        writefile(out, file, 0)
 }
+
+// mkzbootstrap writes cmd/internal/obj/zbootstrap.go:
+//
+//     package obj
+//
+//     const defaultGOROOT = <goroot>
+//     const defaultGOARM = <goarm>
+//     const defaultGOOS = <goos>
+//     const defaultGOARCH = <goarch>
+//     const version = <version>
+//     const goexperiment = <goexperiment>
+//
+func mkzbootstrap(file string) {
+       out := fmt.Sprintf(
+               "// auto generated by go tool dist\n"+
+                       "\n"+
+                       "package obj\n"+
+                       "\n"+
+                       "const defaultGOROOT = `%s`\n"+
+                       "const defaultGOARM = `%s`\n"+
+                       "const defaultGOOS = `%s`\n"+
+                       "const defaultGOARCH = `%s`\n"+
+                       "const version = `%s`\n"+
+                       "const goexperiment = `%s`\n",
+               goroot_final, goarm, gohostos, gohostarch, goversion, os.Getenv("GOEXPERIMENT"))
+
+       writefile(out, file, 0)
+}
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
new file mode 100644 (file)
index 0000000..6cfe4c7
--- /dev/null
@@ -0,0 +1,129 @@
+// Copyright 2015 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.
+
+// Build toolchain using Go 1.4.
+//
+// The general strategy is to copy the source files we need into
+// a new GOPATH workspace, adjust import paths appropriately,
+// invoke the Go 1.4 go command to build those sources,
+// and then copy the binaries back.
+
+package main
+
+import (
+       "os"
+       "strings"
+)
+
+// bootstrapDirs is a list of directories holding code that must be
+// compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
+// All directories in this list are relative to and must be below $GOROOT/src/cmd.
+// The list is assumed to have two kinds of entries: names without slashes,
+// which are commands, and entries beginning with internal/, which are
+// packages supporting the commands.
+var bootstrapDirs = []string{
+       "internal/asm",
+       "internal/obj",
+       "internal/obj/arm",
+       "internal/obj/i386",
+       "internal/obj/ppc64",
+       "internal/obj/x86",
+       "new5a",
+       "new6a",
+       "new8a",
+       "new9a",
+       "objwriter",
+}
+
+func bootstrapBuildTools() {
+       goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
+       if goroot_bootstrap == "" {
+               goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
+       }
+       xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap)
+
+       mkzbootstrap(pathf("%s/src/cmd/internal/obj/zbootstrap.go", goroot))
+
+       // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
+       // We use a subdirectory of $GOROOT/pkg because that's the
+       // space within $GOROOT where we store all generated objects.
+       // We could use a temporary directory outside $GOROOT instead,
+       // but it is easier to debug on failure if the files are in a known location.
+       workspace := pathf("%s/pkg/bootstrap", goroot)
+       xremoveall(workspace)
+       base := pathf("%s/src/bootstrap", workspace)
+       xmkdirall(base)
+
+       // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
+       for _, dir := range bootstrapDirs {
+               src := pathf("%s/src/cmd/%s", goroot, dir)
+               dst := pathf("%s/%s", base, dir)
+               xmkdirall(dst)
+               for _, name := range xreaddirfiles(src) {
+                       srcFile := pathf("%s/%s", src, name)
+                       text := readfile(srcFile)
+                       text = bootstrapFixImports(text, srcFile)
+                       writefile(text, pathf("%s/%s", dst, name), 0)
+               }
+       }
+
+       // Set up environment for invoking Go 1.4 go command.
+       // GOROOT points at Go 1.4 GOROOT,
+       // GOPATH points at our bootstrap workspace,
+       // GOBIN is empty, so that binaries are installed to GOPATH/bin,
+       // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty,
+       // so that Go 1.4 builds whatever kind of binary it knows how to build.
+       // Restore GOROOT, GOPATH, and GOBIN when done.
+       // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH,
+       // because setup will take care of those when bootstrapBuildTools returns.
+
+       defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
+       os.Setenv("GOROOT", goroot_bootstrap)
+
+       defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
+       os.Setenv("GOPATH", workspace)
+
+       defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
+       os.Setenv("GOBIN", "")
+
+       os.Setenv("GOOS", "")
+       os.Setenv("GOHOSTOS", "")
+       os.Setenv("GOARCH", "")
+       os.Setenv("GOHOSTARCH", "")
+
+       // Run Go 1.4 to build binaries.
+       run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-v", "bootstrap/...")
+
+       // Copy binaries into tool binary directory.
+       for _, name := range bootstrapDirs {
+               if !strings.Contains(name, "/") {
+                       copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), 1)
+               }
+       }
+
+       xprintf("\n")
+}
+
+func bootstrapFixImports(text, srcFile string) string {
+       lines := strings.SplitAfter(text, "\n")
+       inBlock := false
+       for i, line := range lines {
+               if strings.HasPrefix(line, "import (") {
+                       inBlock = true
+                       continue
+               }
+               if inBlock && strings.HasPrefix(line, ")") {
+                       inBlock = false
+                       continue
+               }
+               if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
+                       inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
+                       lines[i] = strings.Replace(line, `"cmd/internal/`, `"bootstrap/internal/`, -1)
+               }
+       }
+
+       lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n" + lines[0]
+
+       return strings.Join(lines, "")
+}
index 9ce0749ff3285b5e30d73385f072ed1ef9d35f3f..decbb0ffd2f8d807b93488ffea3a810d30f4684b 100644 (file)
@@ -84,8 +84,23 @@ func run(dir string, mode int, cmd ...string) string {
 
        xcmd := exec.Command(cmd[0], cmd[1:]...)
        xcmd.Dir = dir
+       var data []byte
        var err error
-       data, err := xcmd.CombinedOutput()
+
+       // If we want to show command output and this is not
+       // a background command, assume it's the only thing
+       // running, so we can just let it write directly stdout/stderr
+       // as it runs without fear of mixing the output with some
+       // other command's output. Not buffering lets the output
+       // appear as it is printed instead of once the command exits.
+       // This is most important for the invocation of 'go1.4 build -v bootstrap/...'.
+       if mode&(Background|ShowOutput) == ShowOutput {
+               xcmd.Stdout = os.Stdout
+               xcmd.Stderr = os.Stderr
+               err = xcmd.Run()
+       } else {
+               data, err = xcmd.CombinedOutput()
+       }
        if err != nil && mode&CheckExit != 0 {
                outputLock.Lock()
                if len(data) > 0 {
@@ -275,7 +290,7 @@ func xremoveall(p string) {
        os.RemoveAll(p)
 }
 
-// xreaddir replaces dst with a list of the names of the files in dir.
+// xreaddir replaces dst with a list of the names of the files and subdirectories in dir.
 // The names are relative to dir; they are not full paths.
 func xreaddir(dir string) []string {
        f, err := os.Open(dir)
@@ -290,6 +305,27 @@ func xreaddir(dir string) []string {
        return names
 }
 
+// xreaddir replaces dst with a list of the names of the files in dir.
+// The names are relative to dir; they are not full paths.
+func xreaddirfiles(dir string) []string {
+       f, err := os.Open(dir)
+       if err != nil {
+               fatal("%v", err)
+       }
+       defer f.Close()
+       infos, err := f.Readdir(-1)
+       if err != nil {
+               fatal("reading %s: %v", dir, err)
+       }
+       var names []string
+       for _, fi := range infos {
+               if !fi.IsDir() {
+                       names = append(names, fi.Name())
+               }
+       }
+       return names
+}
+
 // xworkdir creates a new temporary directory to hold object files
 // and returns the name of that directory.
 func xworkdir() string {
@@ -370,6 +406,8 @@ func main() {
                if gohostarch == "" {
                        fatal("$objtype is unset")
                }
+       case "windows":
+               exe = ".exe"
        }
 
        sysinit()
index b2cb7227c616ed34f3abb1d9d461196ef8fda922..d6abd6860576ea4bd80c11846caf82e4f3686003 100644 (file)
@@ -1675,11 +1675,40 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
        return ofile, output, err
 }
 
+// verifyAsm specifies whether to check the assemblers written in Go
+// against the assemblers written in C. If set, asm will run both (say) 6a and new6a
+// and fail if the two produce different output files.
+const verifyAsm = false
+
 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
        // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
        inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
        sfile = mkAbs(p.Dir, sfile)
-       return b.run(p.Dir, p.ImportPath, nil, stringList(buildToolExec, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile))
+       args := []interface{}{buildToolExec, tool(archChar + "a"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, sfile}
+       if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
+               return err
+       }
+       if verifyAsm {
+               newArgs := make([]interface{}, len(args))
+               copy(newArgs, args)
+               newArgs[0] = tool("new" + archChar + "a")
+               newArgs[2] = ofile + ".new" // x.6 becomes x.6.new
+               if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil {
+                       return err
+               }
+               data1, err := ioutil.ReadFile(ofile)
+               if err != nil {
+                       return err
+               }
+               data2, err := ioutil.ReadFile(ofile + ".new")
+               if err != nil {
+                       return err
+               }
+               if !bytes.Equal(data1, data2) {
+                       return fmt.Errorf("%sa and n%sa produced different output files:\n%s\n%s", archChar, archChar, strings.Join(stringList(args...), " "), strings.Join(stringList(newArgs...), " "))
+               }
+       }
+       return nil
 }
 
 func (gcToolchain) pkgpath(basedir string, p *Package) string {
index f3dfc8824f979cdae5d3c4ea9ebce28f70b0aa7f..1482a3958220051683edf23f2eb5269ca279c09d 100644 (file)
@@ -662,7 +662,7 @@ func stringList(args ...interface{}) []string {
                case string:
                        x = append(x, arg)
                default:
-                       panic("stringList: invalid argument")
+                       panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
                }
        }
        return x
index f9fbe9c452e2b824400e365d77c6d1da7f690418..ecb39d900ab5b96c2ecb256dcf8844adbd669407 100644 (file)
@@ -394,10 +394,16 @@ var goTools = map[string]targetDir{
        "cmd/addr2line":                        toTool,
        "cmd/api":                              toTool,
        "cmd/cgo":                              toTool,
+       "cmd/dist":                             toTool,
        "cmd/fix":                              toTool,
        "cmd/link":                             toTool,
+       "cmd/new5a":                            toTool,
+       "cmd/new6a":                            toTool,
+       "cmd/new8a":                            toTool,
+       "cmd/new9a":                            toTool,
        "cmd/nm":                               toTool,
        "cmd/objdump":                          toTool,
+       "cmd/objwriter":                        toTool,
        "cmd/pack":                             toTool,
        "cmd/pprof":                            toTool,
        "cmd/yacc":                             toTool,
diff --git a/src/cmd/internal/asm/asm.go b/src/cmd/internal/asm/asm.go
new file mode 100644 (file)
index 0000000..71c6b1a
--- /dev/null
@@ -0,0 +1,311 @@
+// Inferno utils/6a/a.h and lex.c.
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.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.
+
+// Package asm holds code shared among the assemblers.
+package asm
+
+import (
+       "flag"
+       "fmt"
+       "log"
+       "os"
+       "path/filepath"
+       "strconv"
+       "strings"
+
+       "cmd/internal/obj"
+)
+
+// Initialized by client.
+var (
+       LSCONST int
+       LCONST  int
+       LFCONST int
+       LNAME   int
+       LVAR    int
+       LLAB    int
+
+       Thechar     rune
+       Thestring   string
+       Thelinkarch *obj.LinkArch
+
+       Arches map[string]*obj.LinkArch
+
+       Cclean  func()
+       Yyparse func()
+       Syminit func(*Sym)
+
+       Lexinit []Lextab
+)
+
+type Lextab struct {
+       Name  string
+       Type  int
+       Value int64
+}
+
+const (
+       MAXALIGN = 7
+       FPCHIP   = 1
+       NSYMB    = 500
+       BUFSIZ   = 8192
+       HISTSZ   = 20
+       EOF      = -1
+       IGN      = -2
+       NHASH    = 503
+       STRINGSZ = 200
+       NMACRO   = 10
+)
+
+const (
+       CLAST = iota
+       CMACARG
+       CMACRO
+       CPREPROC
+)
+
+type Macro struct {
+       Text string
+       Narg int
+       Dots bool
+}
+
+type Sym struct {
+       Link      *Sym
+       Ref       *Ref
+       Macro     *Macro
+       Value     int64
+       Type      int
+       Name      string
+       Labelname string
+       Sym       int8
+}
+
+type Ref struct {
+       Class int
+}
+
+type Io struct {
+       Link *Io
+       P    []byte
+       F    *os.File
+       B    [1024]byte
+}
+
+var fi struct {
+       P []byte
+}
+
+var (
+       debug    [256]int
+       hash     = map[string]*Sym{}
+       Dlist    []string
+       newflag  int
+       hunk     string
+       include  []string
+       iofree   *Io
+       ionext   *Io
+       iostack  *Io
+       Lineno   int32
+       nerrors  int
+       nhunk    int32
+       ninclude int
+       nsymb    int32
+       nullgen  obj.Addr
+       outfile  string
+       Pass     int
+       PC       int32
+       peekc    int = IGN
+       sym      int
+       symb     string
+       thunk    int32
+       obuf     obj.Biobuf
+       Ctxt     *obj.Link
+       bstdout  obj.Biobuf
+)
+
+func dodef(p string) {
+       Dlist = append(Dlist, p)
+}
+
+func usage() {
+       fmt.Printf("usage: %ca [options] file.c...\n", Thechar)
+       flag.PrintDefaults()
+       errorexit()
+}
+
+func Main() {
+       var p string
+
+       // Allow GOARCH=Thestring or GOARCH=Thestringsuffix,
+       // but not other values.
+       p = obj.Getgoarch()
+
+       if !strings.HasPrefix(p, Thestring) {
+               log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
+       }
+       if p != Thestring {
+               Thelinkarch = Arches[p]
+               if Thelinkarch == nil {
+                       log.Fatalf("unknown arch %s", p)
+               }
+       }
+
+       Ctxt = obj.Linknew(Thelinkarch)
+       Ctxt.Diag = Yyerror
+       Ctxt.Bso = &bstdout
+       Ctxt.Enforce_data_order = 1
+       bstdout = *obj.Binitw(os.Stdout)
+
+       debug = [256]int{}
+       cinit()
+       outfile = ""
+       setinclude(".")
+
+       flag.Var(flagFn(dodef), "D", "name[=value]: add #define")
+       flag.Var(flagFn(setinclude), "I", "dir: add dir to include path")
+       flag.Var((*count)(&debug['S']), "S", "print assembly and machine code")
+       flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros")
+       flag.StringVar(&outfile, "o", "", "file: set output file")
+       flag.StringVar(&Ctxt.Trimpath, "trimpath", "", "prefix: remove prefix from recorded source file paths")
+
+       flag.Parse()
+
+       Ctxt.Debugasm = int32(debug['S'])
+
+       if flag.NArg() < 1 {
+               usage()
+       }
+       if flag.NArg() > 1 {
+               fmt.Printf("can't assemble multiple files\n")
+               errorexit()
+       }
+
+       if assemble(flag.Arg(0)) != 0 {
+               errorexit()
+       }
+       obj.Bflush(&bstdout)
+       if nerrors > 0 {
+               errorexit()
+       }
+}
+
+func assemble(file string) int {
+       var i int
+
+       if outfile == "" {
+               outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar)
+       }
+
+       of, err := os.Create(outfile)
+       if err != nil {
+               Yyerror("%ca: cannot create %s", Thechar, outfile)
+               errorexit()
+       }
+
+       obuf = *obj.Binitw(of)
+       fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
+       fmt.Fprintf(&obuf, "!\n")
+
+       for Pass = 1; Pass <= 2; Pass++ {
+               pinit(file)
+               for i = 0; i < len(Dlist); i++ {
+                       dodefine(Dlist[i])
+               }
+               Yyparse()
+               Cclean()
+               if nerrors != 0 {
+                       return nerrors
+               }
+       }
+
+       obj.Writeobjdirect(Ctxt, &obuf)
+       obj.Bflush(&obuf)
+       return 0
+}
+
+func cinit() {
+       for i := 0; i < len(Lexinit); i++ {
+               s := Lookup(Lexinit[i].Name)
+               if s.Type != LNAME {
+                       Yyerror("double initialization %s", Lexinit[i].Name)
+               }
+               s.Type = Lexinit[i].Type
+               s.Value = Lexinit[i].Value
+       }
+}
+
+func syminit(s *Sym) {
+       s.Type = LNAME
+       s.Value = 0
+}
+
+type flagFn func(string)
+
+func (flagFn) String() string {
+       return "<arg>"
+}
+
+func (f flagFn) Set(s string) error {
+       f(s)
+       return nil
+}
+
+type yyImpl struct{}
+
+// count is a flag.Value that is like a flag.Bool and a flag.Int.
+// If used as -name, it increments the count, but -name=x sets the count.
+// Used for verbose flag -v.
+type count int
+
+func (c *count) String() string {
+       return fmt.Sprint(int(*c))
+}
+
+func (c *count) Set(s string) error {
+       switch s {
+       case "true":
+               *c++
+       case "false":
+               *c = 0
+       default:
+               n, err := strconv.Atoi(s)
+               if err != nil {
+                       return fmt.Errorf("invalid count %q", s)
+               }
+               *c = count(n)
+       }
+       return nil
+}
+
+func (c *count) IsBoolFlag() bool {
+       return true
+}
diff --git a/src/cmd/internal/asm/lexbody.go b/src/cmd/internal/asm/lexbody.go
new file mode 100644 (file)
index 0000000..14a82f8
--- /dev/null
@@ -0,0 +1,738 @@
+// Inferno utils/cc/lexbody
+// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/lexbody
+//
+//     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.
+
+package asm
+
+import (
+       "bytes"
+       "fmt"
+       "os"
+       "strconv"
+       "strings"
+       "unicode/utf8"
+
+       "cmd/internal/obj"
+)
+
+/*
+ * common code for all the assemblers
+ */
+func pragpack() {
+
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragvararg() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragcgo(name string) {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragfpround() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragtextflag() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragdataflag() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragprofile() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func pragincomplete() {
+       for getnsc() != '\n' {
+
+       }
+}
+
+func setinclude(p string) {
+       var i int
+
+       if p == "" {
+               return
+       }
+       for i = 1; i < len(include); i++ {
+               if p == include[i] {
+                       return
+               }
+       }
+
+       include = append(include, p)
+}
+
+func errorexit() {
+       obj.Bflush(&bstdout)
+       if outfile != "" {
+               os.Remove(outfile)
+       }
+       os.Exit(2)
+}
+
+func pushio() {
+       var i *Io
+
+       i = iostack
+       if i == nil {
+               Yyerror("botch in pushio")
+               errorexit()
+       }
+
+       i.P = fi.P
+}
+
+func newio() {
+       var i *Io
+       var pushdepth int = 0
+
+       i = iofree
+       if i == nil {
+               pushdepth++
+               if pushdepth > 1000 {
+                       Yyerror("macro/io expansion too deep")
+                       errorexit()
+               }
+               i = new(Io)
+       } else {
+               iofree = i.Link
+       }
+       i.F = nil
+       i.P = nil
+       ionext = i
+}
+
+func newfile(s string, f *os.File) {
+       var i *Io
+
+       i = ionext
+       i.Link = iostack
+       iostack = i
+       i.F = f
+       if f == nil {
+               var err error
+               i.F, err = os.Open(s)
+               if err != nil {
+                       Yyerror("%ca: %v", Thechar, err)
+                       errorexit()
+               }
+       }
+
+       fi.P = nil
+       obj.Linklinehist(Ctxt, int(Lineno), s, 0)
+}
+
+var thetext *obj.LSym
+
+func Settext(s *obj.LSym) {
+       thetext = s
+}
+
+func LabelLookup(s *Sym) *Sym {
+       var p string
+       var lab *Sym
+
+       if thetext == nil {
+               s.Labelname = s.Name
+               return s
+       }
+
+       p = string(fmt.Sprintf("%s.%s", thetext.Name, s.Name))
+       lab = Lookup(p)
+
+       lab.Labelname = s.Name
+       return lab
+}
+
+func Lookup(symb string) *Sym {
+       // turn leading Â· into ""·
+       if strings.HasPrefix(symb, "·") {
+               symb = `""` + symb
+       }
+
+       // turn Â· (U+00B7) into .
+       // turn âˆ• (U+2215) into /
+       symb = strings.Replace(symb, "·", ".", -1)
+       symb = strings.Replace(symb, "∕", "/", -1)
+
+       s := hash[symb]
+       if s != nil {
+               return s
+       }
+
+       s = new(Sym)
+       s.Name = symb
+       syminit(s)
+       hash[symb] = s
+       return s
+}
+
+func isalnum(c int) bool {
+       return isalpha(c) || isdigit(c)
+}
+
+func isalpha(c int) bool {
+       return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
+}
+
+func isspace(c int) bool {
+       return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+}
+
+func ISALPHA(c int) bool {
+       if isalpha(c) {
+               return true
+       }
+       if c >= utf8.RuneSelf {
+               return true
+       }
+       return false
+}
+
+var yybuf bytes.Buffer
+
+func (yyImpl) Error(s string) {
+       Yyerror("%s", s)
+}
+
+type Yylval struct {
+       Sym  *Sym
+       Lval int64
+       Sval string
+       Dval float64
+}
+
+func Yylex(yylval *Yylval) int {
+       var c int
+       var c1 int
+       var s *Sym
+
+       c = peekc
+       if c != IGN {
+               peekc = IGN
+               goto l1
+       }
+
+l0:
+       c = GETC()
+
+l1:
+       if c == EOF {
+               peekc = EOF
+               return -1
+       }
+
+       if isspace(c) {
+               if c == '\n' {
+                       Lineno++
+                       return ';'
+               }
+
+               goto l0
+       }
+
+       if ISALPHA(c) {
+               yybuf.Reset()
+               goto aloop
+       }
+       if isdigit(c) {
+               goto tnum
+       }
+       switch c {
+       case '\n':
+               Lineno++
+               return ';'
+
+       case '#':
+               domacro()
+               goto l0
+
+       case '.':
+               c = GETC()
+               if ISALPHA(c) {
+                       yybuf.Reset()
+                       yybuf.WriteByte('.')
+                       goto aloop
+               }
+
+               if isdigit(c) {
+                       yybuf.Reset()
+                       yybuf.WriteByte('.')
+                       goto casedot
+               }
+
+               peekc = c
+               return '.'
+
+       case '_',
+               '@':
+               yybuf.Reset()
+               goto aloop
+
+       case '"':
+               var buf bytes.Buffer
+               c1 = 0
+               for {
+                       c = escchar('"')
+                       if c == EOF {
+                               break
+                       }
+                       buf.WriteByte(byte(c))
+               }
+               yylval.Sval = buf.String()
+               return LSCONST
+
+       case '\'':
+               c = escchar('\'')
+               if c == EOF {
+                       c = '\''
+               }
+               if escchar('\'') != EOF {
+                       Yyerror("missing '")
+               }
+               yylval.Lval = int64(c)
+               return LCONST
+
+       case '/':
+               c1 = GETC()
+               if c1 == '/' {
+                       for {
+                               c = GETC()
+                               if c == '\n' {
+                                       goto l1
+                               }
+                               if c == EOF {
+                                       Yyerror("eof in comment")
+                                       errorexit()
+                               }
+                       }
+               }
+
+               if c1 == '*' {
+                       for {
+                               c = GETC()
+                               for c == '*' {
+                                       c = GETC()
+                                       if c == '/' {
+                                               goto l0
+                                       }
+                               }
+
+                               if c == EOF {
+                                       Yyerror("eof in comment")
+                                       errorexit()
+                               }
+
+                               if c == '\n' {
+                                       Lineno++
+                               }
+                       }
+               }
+
+       default:
+               return int(c)
+       }
+
+       peekc = c1
+       return int(c)
+
+casedot:
+       for {
+               yybuf.WriteByte(byte(c))
+               c = GETC()
+               if !(isdigit(c)) {
+                       break
+               }
+       }
+
+       if c == 'e' || c == 'E' {
+               goto casee
+       }
+       goto caseout
+
+casee:
+       yybuf.WriteByte('e')
+       c = GETC()
+       if c == '+' || c == '-' {
+               yybuf.WriteByte(byte(c))
+               c = GETC()
+       }
+
+       for isdigit(c) {
+               yybuf.WriteByte(byte(c))
+               c = GETC()
+       }
+
+caseout:
+       peekc = c
+       if FPCHIP != 0 /*TypeKind(100016)*/ {
+               last = yybuf.String()
+               yylval.Dval = atof(last)
+               return LFCONST
+       }
+
+       Yyerror("assembler cannot interpret fp constants")
+       yylval.Lval = 1
+       return LCONST
+
+aloop:
+       yybuf.WriteByte(byte(c))
+       c = GETC()
+       if ISALPHA(c) || isdigit(c) || c == '_' || c == '$' {
+               goto aloop
+       }
+       peekc = c
+       last = yybuf.String()
+       s = Lookup(last)
+       if s.Macro != nil {
+               newio()
+               ionext.P = macexpand(s)
+               pushio()
+               ionext.Link = iostack
+               iostack = ionext
+               fi.P = ionext.P
+               if peekc != IGN {
+                       fi.P = append(fi.P, byte(peekc))
+                       peekc = IGN
+               }
+
+               goto l0
+       }
+
+       if s.Type == 0 {
+               s.Type = LNAME
+       }
+       if s.Type == LNAME || s.Type == LVAR || s.Type == LLAB {
+               yylval.Sym = s
+               yylval.Sval = last
+               return int(s.Type)
+       }
+
+       yylval.Lval = s.Value
+       yylval.Sval = last
+       return int(s.Type)
+
+tnum:
+       yybuf.Reset()
+       if c != '0' {
+               goto dc
+       }
+       yybuf.WriteByte(byte(c))
+       c = GETC()
+       c1 = 3
+       if c == 'x' || c == 'X' {
+               c1 = 4
+               c = GETC()
+       } else if c < '0' || c > '7' {
+               goto dc
+       }
+       yylval.Lval = 0
+       for {
+               if c >= '0' && c <= '9' {
+                       if c > '7' && c1 == 3 {
+                               break
+                       }
+                       yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
+                       yylval.Lval += int64(c) - '0'
+                       c = GETC()
+                       continue
+               }
+
+               if c1 == 3 {
+                       break
+               }
+               if c >= 'A' && c <= 'F' {
+                       c += 'a' - 'A'
+               }
+               if c >= 'a' && c <= 'f' {
+                       yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
+                       yylval.Lval += int64(c) - 'a' + 10
+                       c = GETC()
+                       continue
+               }
+
+               break
+       }
+
+       goto ncu
+
+dc:
+       for {
+               if !(isdigit(c)) {
+                       break
+               }
+               yybuf.WriteByte(byte(c))
+               c = GETC()
+       }
+
+       if c == '.' {
+               goto casedot
+       }
+       if c == 'e' || c == 'E' {
+               goto casee
+       }
+       last = yybuf.String()
+       yylval.Lval = strtoll(last, nil, 10)
+
+ncu:
+       for c == 'U' || c == 'u' || c == 'l' || c == 'L' {
+               c = GETC()
+       }
+       peekc = c
+       return LCONST
+}
+
+func getc() int {
+       var c int
+
+       c = peekc
+       if c != IGN {
+               peekc = IGN
+               if c == '\n' {
+                       Lineno++
+               }
+               return c
+       }
+
+       c = GETC()
+       if c == '\n' {
+               Lineno++
+       }
+       if c == EOF {
+               Yyerror("End of file")
+               errorexit()
+       }
+
+       return c
+}
+
+func getnsc() int {
+       var c int
+
+       for {
+               c = getc()
+               if !isspace(c) || c == '\n' {
+                       return c
+               }
+       }
+}
+
+func unget(c int) {
+       peekc = c
+       if c == '\n' {
+               Lineno--
+       }
+}
+
+func escchar(e int) int {
+       var c int
+       var l int
+
+loop:
+       c = getc()
+       if c == '\n' {
+               Yyerror("newline in string")
+               return EOF
+       }
+
+       if c != '\\' {
+               if c == e {
+                       return EOF
+               }
+               return c
+       }
+
+       c = getc()
+       if c >= '0' && c <= '7' {
+               l = c - '0'
+               c = getc()
+               if c >= '0' && c <= '7' {
+                       l = l*8 + c - '0'
+                       c = getc()
+                       if c >= '0' && c <= '7' {
+                               l = l*8 + c - '0'
+                               return l
+                       }
+               }
+
+               peekc = c
+               unget(c)
+               return l
+       }
+
+       switch c {
+       case '\n':
+               goto loop
+       case 'n':
+               return '\n'
+       case 't':
+               return '\t'
+       case 'b':
+               return '\b'
+       case 'r':
+               return '\r'
+       case 'f':
+               return '\f'
+       case 'a':
+               return 0x07
+       case 'v':
+               return 0x0b
+       case 'z':
+               return 0x00
+       }
+
+       return c
+}
+
+func pinit(f string) {
+       Lineno = 1
+       newio()
+       newfile(f, nil)
+       PC = 0
+       peekc = IGN
+       sym = 1
+       for _, s := range hash {
+               s.Macro = nil
+       }
+}
+
+func filbuf() int {
+       var i *Io
+       var n int
+
+loop:
+       i = iostack
+       if i == nil {
+               return EOF
+       }
+       if i.F == nil {
+               goto pop
+       }
+       n, _ = i.F.Read(i.B[:])
+       if n == 0 {
+               i.F.Close()
+               obj.Linklinehist(Ctxt, int(Lineno), "<pop>", 0)
+               goto pop
+       }
+       fi.P = i.B[1:n]
+       return int(i.B[0]) & 0xff
+
+pop:
+       iostack = i.Link
+       i.Link = iofree
+       iofree = i
+       i = iostack
+       if i == nil {
+               return EOF
+       }
+       fi.P = i.P
+       if len(fi.P) == 0 {
+               goto loop
+       }
+       tmp8 := fi.P
+       fi.P = fi.P[1:]
+       return int(tmp8[0]) & 0xff
+}
+
+var last string
+
+func Yyerror(a string, args ...interface{}) {
+       /*
+        * hack to intercept message from yaccpar
+        */
+       if a == "syntax error" || len(args) == 1 && a == "%s" && args[0] == "syntax error" {
+               Yyerror("syntax error, last name: %s", last)
+               return
+       }
+
+       prfile(Lineno)
+       fmt.Printf("%s\n", fmt.Sprintf(a, args...))
+       nerrors++
+       if nerrors > 10 {
+               fmt.Printf("too many errors\n")
+               errorexit()
+       }
+}
+
+func prfile(l int32) {
+       obj.Linkprfile(Ctxt, int(l))
+}
+
+func GETC() int {
+       var c int
+       if len(fi.P) == 0 {
+               return filbuf()
+       }
+       c = int(fi.P[0])
+       fi.P = fi.P[1:]
+       return c
+}
+
+func isdigit(c int) bool {
+       return '0' <= c && c <= '9'
+}
+
+func strtoll(s string, p *byte, base int) int64 {
+       if p != nil {
+               panic("strtoll")
+       }
+       n, err := strconv.ParseInt(s, base, 64)
+       if err != nil {
+               return 0
+       }
+       return n
+}
+
+func atof(s string) float64 {
+       f, err := strconv.ParseFloat(s, 64)
+       if err != nil {
+               return 0
+       }
+       return f
+}
diff --git a/src/cmd/internal/asm/macbody.go b/src/cmd/internal/asm/macbody.go
new file mode 100644 (file)
index 0000000..337692a
--- /dev/null
@@ -0,0 +1,885 @@
+// Inferno utils/cc/macbody
+// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody
+//
+//     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.
+
+package asm
+
+import (
+       "bytes"
+       "cmd/internal/obj"
+       "fmt"
+       "os"
+       "strings"
+)
+
+const (
+       VARMAC = 0x80
+)
+
+func getnsn() int32 {
+       var n int32
+       var c int
+
+       c = getnsc()
+       if c < '0' || c > '9' {
+               return -1
+       }
+       n = 0
+       for c >= '0' && c <= '9' {
+               n = n*10 + int32(c) - '0'
+               c = getc()
+       }
+
+       unget(c)
+       return n
+}
+
+func getsym() *Sym {
+       var c int
+
+       c = getnsc()
+       if !isalpha(c) && c != '_' && c < 0x80 {
+               unget(c)
+               return nil
+       }
+
+       var buf bytes.Buffer
+       for {
+               buf.WriteByte(byte(c))
+               c = getc()
+               if isalnum(c) || c == '_' || c >= 0x80 {
+                       continue
+               }
+               unget(c)
+               break
+       }
+       last = buf.String()
+       return Lookup(last)
+}
+
+func getsymdots(dots *int) *Sym {
+       var c int
+       var s *Sym
+
+       s = getsym()
+       if s != nil {
+               return s
+       }
+
+       c = getnsc()
+       if c != '.' {
+               unget(c)
+               return nil
+       }
+
+       if getc() != '.' || getc() != '.' {
+               Yyerror("bad dots in macro")
+       }
+       *dots = 1
+       return Lookup("__VA_ARGS__")
+}
+
+func getcom() int {
+       var c int
+
+       for {
+               c = getnsc()
+               if c != '/' {
+                       break
+               }
+               c = getc()
+               if c == '/' {
+                       for c != '\n' {
+                               c = getc()
+                       }
+                       break
+               }
+
+               if c != '*' {
+                       break
+               }
+               c = getc()
+               for {
+                       if c == '*' {
+                               c = getc()
+                               if c != '/' {
+                                       continue
+                               }
+                               c = getc()
+                               break
+                       }
+
+                       if c == '\n' {
+                               Yyerror("comment across newline")
+                               break
+                       }
+
+                       c = getc()
+               }
+
+               if c == '\n' {
+                       break
+               }
+       }
+
+       return c
+}
+
+func dodefine(cp string) {
+       var s *Sym
+       var p string
+
+       if i := strings.Index(cp, "="); i >= 0 {
+               p = cp[i+1:]
+               cp = cp[:i]
+               s = Lookup(cp)
+               s.Macro = &Macro{Text: p}
+       } else {
+               s = Lookup(cp)
+               s.Macro = &Macro{Text: "1"}
+       }
+
+       if debug['m'] != 0 {
+               fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text)
+       }
+}
+
+var mactab = []struct {
+       Macname string
+       Macf    func()
+}{
+       {"ifdef", nil},  /* macif(0) */
+       {"ifndef", nil}, /* macif(1) */
+       {"else", nil},   /* macif(2) */
+       {"line", maclin},
+       {"define", macdef},
+       {"include", macinc},
+       {"undef", macund},
+       {"pragma", macprag},
+       {"endif", macend},
+}
+
+func domacro() {
+       var i int
+       var s *Sym
+
+       s = getsym()
+       if s == nil {
+               s = Lookup("endif")
+       }
+       for i = 0; i < len(mactab); i++ {
+               if s.Name == mactab[i].Macname {
+                       if mactab[i].Macf != nil {
+                               mactab[i].Macf()
+                       } else {
+                               macif(i)
+                       }
+                       return
+               }
+       }
+
+       Yyerror("unknown #: %s", s.Name)
+       macend()
+}
+
+func macund() {
+       var s *Sym
+
+       s = getsym()
+       macend()
+       if s == nil {
+               Yyerror("syntax in #undef")
+               return
+       }
+
+       s.Macro = nil
+}
+
+const (
+       NARG = 25
+)
+
+func macdef() {
+       var s *Sym
+       var a *Sym
+       var args [NARG]string
+       var n int
+       var i int
+       var c int
+       var dots int
+       var ischr int
+       var base bytes.Buffer
+
+       s = getsym()
+       if s == nil {
+               goto bad
+       }
+       if s.Macro != nil {
+               Yyerror("macro redefined: %s", s.Name)
+       }
+       c = getc()
+       n = -1
+       dots = 0
+       if c == '(' {
+               n++
+               c = getnsc()
+               if c != ')' {
+                       unget(c)
+                       for {
+                               a = getsymdots(&dots)
+                               if a == nil {
+                                       goto bad
+                               }
+                               if n >= NARG {
+                                       Yyerror("too many arguments in #define: %s", s.Name)
+                                       goto bad
+                               }
+
+                               args[n] = a.Name
+                               n++
+                               c = getnsc()
+                               if c == ')' {
+                                       break
+                               }
+                               if c != ',' || dots != 0 {
+                                       goto bad
+                               }
+                       }
+               }
+
+               c = getc()
+       }
+
+       if isspace(c) {
+               if c != '\n' {
+                       c = getnsc()
+               }
+       }
+       ischr = 0
+       for {
+               if isalpha(c) || c == '_' {
+                       var buf bytes.Buffer
+                       buf.WriteByte(byte(c))
+                       c = getc()
+                       for isalnum(c) || c == '_' {
+                               buf.WriteByte(byte(c))
+                               c = getc()
+                       }
+
+                       symb := buf.String()
+                       for i = 0; i < n; i++ {
+                               if symb == args[i] {
+                                       break
+                               }
+                       }
+                       if i >= n {
+                               base.WriteString(symb)
+                               continue
+                       }
+
+                       base.WriteByte('#')
+                       base.WriteByte(byte('a' + i))
+                       continue
+               }
+
+               if ischr != 0 {
+                       if c == '\\' {
+                               base.WriteByte(byte(c))
+                               c = getc()
+                       } else if c == ischr {
+                               ischr = 0
+                       }
+               } else {
+
+                       if c == '"' || c == '\'' {
+                               base.WriteByte(byte(c))
+                               ischr = c
+                               c = getc()
+                               continue
+                       }
+
+                       if c == '/' {
+                               c = getc()
+                               if c == '/' {
+                                       c = getc()
+                                       for {
+                                               if c == '\n' {
+                                                       break
+                                               }
+                                               c = getc()
+                                       }
+
+                                       continue
+                               }
+
+                               if c == '*' {
+                                       c = getc()
+                                       for {
+                                               if c == '*' {
+                                                       c = getc()
+                                                       if c != '/' {
+                                                               continue
+                                                       }
+                                                       c = getc()
+                                                       break
+                                               }
+
+                                               if c == '\n' {
+                                                       Yyerror("comment and newline in define: %s", s.Name)
+                                                       break
+                                               }
+
+                                               c = getc()
+                                       }
+
+                                       continue
+                               }
+
+                               base.WriteByte('/')
+                               continue
+                       }
+               }
+
+               if c == '\\' {
+                       c = getc()
+                       if c == '\n' {
+                               c = getc()
+                               continue
+                       } else if c == '\r' {
+                               c = getc()
+                               if c == '\n' {
+                                       c = getc()
+                                       continue
+                               }
+                       }
+
+                       base.WriteByte('\\')
+                       continue
+               }
+
+               if c == '\n' {
+                       break
+               }
+               if c == '#' {
+                       if n > 0 {
+                               base.WriteByte(byte(c))
+                       }
+               }
+
+               base.WriteByte(byte(c))
+               c = GETC()
+               if c == '\n' {
+                       Lineno++
+               }
+               if c == -1 {
+                       Yyerror("eof in a macro: %s", s.Name)
+                       break
+               }
+       }
+
+       s.Macro = &Macro{
+               Text: base.String(),
+               Narg: n + 1,
+               Dots: dots != 0,
+       }
+       if debug['m'] != 0 {
+               fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text)
+       }
+       return
+
+bad:
+       if s == nil {
+               Yyerror("syntax in #define")
+       } else {
+
+               Yyerror("syntax in #define: %s", s.Name)
+       }
+       macend()
+}
+
+func macexpand(s *Sym) []byte {
+       var l int
+       var c int
+       var arg []string
+       var out bytes.Buffer
+       var buf bytes.Buffer
+       var cp string
+
+       if s.Macro.Narg == 0 {
+               if debug['m'] != 0 {
+                       fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text)
+               }
+               return []byte(s.Macro.Text)
+       }
+
+       nargs := s.Macro.Narg - 1
+       dots := s.Macro.Dots
+
+       c = getnsc()
+       if c != '(' {
+               goto bad
+       }
+       c = getc()
+       if c != ')' {
+               unget(c)
+               l = 0
+               for {
+                       c = getc()
+                       if c == '"' {
+                               for {
+                                       buf.WriteByte(byte(c))
+                                       c = getc()
+                                       if c == '\\' {
+                                               buf.WriteByte(byte(c))
+                                               c = getc()
+                                               continue
+                                       }
+
+                                       if c == '\n' {
+                                               goto bad
+                                       }
+                                       if c == '"' {
+                                               break
+                                       }
+                               }
+                       }
+
+                       if c == '\'' {
+                               for {
+                                       buf.WriteByte(byte(c))
+                                       c = getc()
+                                       if c == '\\' {
+                                               buf.WriteByte(byte(c))
+                                               c = getc()
+                                               continue
+                                       }
+
+                                       if c == '\n' {
+                                               goto bad
+                                       }
+                                       if c == '\'' {
+                                               break
+                                       }
+                               }
+                       }
+
+                       if c == '/' {
+                               c = getc()
+                               switch c {
+                               case '*':
+                                       for {
+                                               c = getc()
+                                               if c == '*' {
+                                                       c = getc()
+                                                       if c == '/' {
+                                                               break
+                                                       }
+                                               }
+                                       }
+
+                                       buf.WriteByte(' ')
+                                       continue
+
+                               case '/':
+                                       for {
+                                               c = getc()
+                                               if !(c != '\n') {
+                                                       break
+                                               }
+                                       }
+
+                               default:
+                                       unget(c)
+                                       c = '/'
+                               }
+                       }
+
+                       if l == 0 {
+                               if c == ',' {
+                                       if len(arg) == nargs-1 && dots {
+                                               buf.WriteByte(',')
+                                               continue
+                                       }
+
+                                       arg = append(arg, buf.String())
+                                       buf.Reset()
+                                       continue
+                               }
+
+                               if c == ')' {
+                                       arg = append(arg, buf.String())
+                                       break
+                               }
+                       }
+
+                       if c == '\n' {
+                               c = ' '
+                       }
+                       buf.WriteByte(byte(c))
+                       if c == '(' {
+                               l++
+                       }
+                       if c == ')' {
+                               l--
+                       }
+               }
+       }
+
+       if len(arg) != nargs {
+               Yyerror("argument mismatch expanding: %s", s.Name)
+               return nil
+       }
+
+       cp = s.Macro.Text
+       for i := 0; i < len(cp); i++ {
+               c = int(cp[i])
+               if c == '\n' {
+                       c = ' '
+               }
+               if c != '#' {
+                       out.WriteByte(byte(c))
+                       continue
+               }
+
+               i++
+               if i >= len(cp) {
+                       goto bad
+               }
+               c = int(cp[i])
+               if c == '#' {
+                       out.WriteByte(byte(c))
+                       continue
+               }
+
+               c -= 'a'
+               if c < 0 || c >= len(arg) {
+                       continue
+               }
+               out.WriteString(arg[c])
+       }
+
+       if debug['m'] != 0 {
+               fmt.Printf("#expand %s %s\n", s.Name, out.String())
+       }
+       return out.Bytes()
+
+bad:
+       Yyerror("syntax in macro expansion: %s", s.Name)
+       return nil
+}
+
+func macinc() {
+       var c0 int
+       var c int
+       var i int
+       var buf bytes.Buffer
+       var f *os.File
+       var hp string
+       var str string
+       var symb string
+
+       c0 = getnsc()
+       if c0 != '"' {
+               c = c0
+               if c0 != '<' {
+                       goto bad
+               }
+               c0 = '>'
+       }
+
+       for {
+               c = getc()
+               if c == c0 {
+                       break
+               }
+               if c == '\n' {
+                       goto bad
+               }
+               buf.WriteByte(byte(c))
+       }
+       str = buf.String()
+
+       c = getcom()
+       if c != '\n' {
+               goto bad
+       }
+
+       for i = 0; i < len(include); i++ {
+               if i == 0 && c0 == '>' {
+                       continue
+               }
+               symb = include[i]
+               symb += "/"
+               if symb == "./" {
+                       symb = ""
+               }
+               symb += str
+               var err error
+               f, err = os.Open(symb)
+               if err == nil {
+                       break
+               }
+       }
+
+       if f == nil {
+               symb = str
+       }
+       hp = symb
+       newio()
+       pushio()
+       newfile(hp, f)
+       return
+
+bad:
+       unget(c)
+       Yyerror("syntax in #include")
+       macend()
+}
+
+func maclin() {
+       var c int
+       var n int32
+       var buf bytes.Buffer
+       var symb string
+
+       n = getnsn()
+       c = getc()
+       if n < 0 {
+               goto bad
+       }
+       for {
+               if c == ' ' || c == '\t' {
+                       c = getc()
+                       continue
+               }
+
+               if c == '"' {
+                       break
+               }
+               if c == '\n' {
+                       symb = "<noname>"
+                       goto nn
+               }
+
+               goto bad
+       }
+
+       for {
+               c = getc()
+               if c == '"' {
+                       break
+               }
+               buf.WriteByte(byte(c))
+       }
+       symb = buf.String()
+
+       c = getcom()
+       if c != '\n' {
+               goto bad
+       }
+
+nn:
+       obj.Linklinehist(Ctxt, int(Lineno), symb, int(n))
+       return
+
+bad:
+       unget(c)
+       Yyerror("syntax in #line")
+       macend()
+}
+
+func macif(f int) {
+       var c int
+       var l int
+       var bol int
+       var s *Sym
+
+       if f == 2 {
+               goto skip
+       }
+       s = getsym()
+       if s == nil {
+               goto bad
+       }
+       if getcom() != '\n' {
+               goto bad
+       }
+       if (s.Macro != nil) != (f != 0) {
+               return
+       }
+
+skip:
+       bol = 1
+       l = 0
+       for {
+               c = getc()
+               if c != '#' {
+                       if !isspace(c) {
+                               bol = 0
+                       }
+                       if c == '\n' {
+                               bol = 1
+                       }
+                       continue
+               }
+
+               if !(bol != 0) {
+                       continue
+               }
+               s = getsym()
+               if s == nil {
+                       continue
+               }
+               if s.Name == "endif" {
+                       if l != 0 {
+                               l--
+                               continue
+                       }
+
+                       macend()
+                       return
+               }
+
+               if s.Name == "ifdef" || s.Name == "ifndef" {
+                       l++
+                       continue
+               }
+
+               if l == 0 && f != 2 && s.Name == "else" {
+                       macend()
+                       return
+               }
+       }
+
+bad:
+       Yyerror("syntax in #if(n)def")
+       macend()
+}
+
+func macprag() {
+       var s *Sym
+       var c0 int
+       var c int
+       var buf bytes.Buffer
+       var symb string
+
+       s = getsym()
+
+       if s != nil && s.Name == "lib" {
+               goto praglib
+       }
+       if s != nil && s.Name == "pack" {
+               pragpack()
+               return
+       }
+
+       if s != nil && s.Name == "fpround" {
+               pragfpround()
+               return
+       }
+
+       if s != nil && s.Name == "textflag" {
+               pragtextflag()
+               return
+       }
+
+       if s != nil && s.Name == "dataflag" {
+               pragdataflag()
+               return
+       }
+
+       if s != nil && s.Name == "varargck" {
+               pragvararg()
+               return
+       }
+
+       if s != nil && s.Name == "incomplete" {
+               pragincomplete()
+               return
+       }
+
+       if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) {
+               pragcgo(s.Name)
+               return
+       }
+
+       for getnsc() != '\n' {
+
+       }
+       return
+
+praglib:
+       c0 = getnsc()
+       if c0 != '"' {
+               c = c0
+               if c0 != '<' {
+                       goto bad
+               }
+               c0 = '>'
+       }
+
+       for {
+               c = getc()
+               if c == c0 {
+                       break
+               }
+               if c == '\n' {
+                       goto bad
+               }
+               buf.WriteByte(byte(c))
+       }
+       symb = buf.String()
+
+       c = getcom()
+       if c != '\n' {
+               goto bad
+       }
+
+       /*
+        * put pragma-line in as a funny history
+        */
+       obj.Linklinehist(Ctxt, int(Lineno), symb, -1)
+       return
+
+bad:
+       unget(c)
+       Yyerror("syntax in #pragma lib")
+       macend()
+}
+
+func macend() {
+       var c int
+
+       for {
+               c = getnsc()
+               if c < 0 || c == '\n' {
+                       return
+               }
+       }
+}
diff --git a/src/cmd/internal/obj/arm/5.out.go b/src/cmd/internal/obj/arm/5.out.go
new file mode 100644 (file)
index 0000000..a1edfff
--- /dev/null
@@ -0,0 +1,305 @@
+// Inferno utils/5c/5.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/5.out.h
+//
+//     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.
+
+package arm
+
+// list[5689].c
+
+// obj.c
+
+// objfile.c
+
+// pass.c
+
+// pcln.c
+
+// sym.c
+
+// TODO(ality): remove this workaround.
+//   It's here because Pconv in liblink/list?.c references %L.
+
+const (
+       NSNAME = 8
+       NSYM   = 50
+       NREG   = 16
+)
+
+/* -1 disables use of REGARG */
+const (
+       REGARG = -1
+)
+
+const (
+       REGRET  = 0
+       REGEXT  = 10
+       REGG    = REGEXT - 0
+       REGM    = REGEXT - 1
+       REGTMP  = 11
+       REGSP   = 13
+       REGLINK = 14
+       REGPC   = 15
+       NFREG   = 16
+       FREGRET = 0
+       FREGEXT = 7
+       FREGTMP = 15
+)
+
+/* compiler allocates register variables F0 up */
+/* compiler allocates external registers F7 down */
+const (
+       C_NONE = iota
+       C_REG
+       C_REGREG
+       C_REGREG2
+       C_SHIFT
+       C_FREG
+       C_PSR
+       C_FCR
+       C_RCON
+       C_NCON
+       C_SCON
+       C_LCON
+       C_LCONADDR
+       C_ZFCON
+       C_SFCON
+       C_LFCON
+       C_RACON
+       C_LACON
+       C_SBRA
+       C_LBRA
+       C_HAUTO
+       C_FAUTO
+       C_HFAUTO
+       C_SAUTO
+       C_LAUTO
+       C_HOREG
+       C_FOREG
+       C_HFOREG
+       C_SOREG
+       C_ROREG
+       C_SROREG
+       C_LOREG
+       C_PC
+       C_SP
+       C_HREG
+       C_ADDR
+       C_GOK
+       C_NCLASS
+)
+
+const (
+       AXXX = iota
+       AAND
+       AEOR
+       ASUB
+       ARSB
+       AADD
+       AADC
+       ASBC
+       ARSC
+       ATST
+       ATEQ
+       ACMP
+       ACMN
+       AORR
+       ABIC
+       AMVN
+       AB
+       ABL
+       ABEQ
+       ABNE
+       ABCS
+       ABHS
+       ABCC
+       ABLO
+       ABMI
+       ABPL
+       ABVS
+       ABVC
+       ABHI
+       ABLS
+       ABGE
+       ABLT
+       ABGT
+       ABLE
+       AMOVWD
+       AMOVWF
+       AMOVDW
+       AMOVFW
+       AMOVFD
+       AMOVDF
+       AMOVF
+       AMOVD
+       ACMPF
+       ACMPD
+       AADDF
+       AADDD
+       ASUBF
+       ASUBD
+       AMULF
+       AMULD
+       ADIVF
+       ADIVD
+       ASQRTF
+       ASQRTD
+       AABSF
+       AABSD
+       ASRL
+       ASRA
+       ASLL
+       AMULU
+       ADIVU
+       AMUL
+       ADIV
+       AMOD
+       AMODU
+       AMOVB
+       AMOVBS
+       AMOVBU
+       AMOVH
+       AMOVHS
+       AMOVHU
+       AMOVW
+       AMOVM
+       ASWPBU
+       ASWPW
+       ANOP
+       ARFE
+       ASWI
+       AMULA
+       ADATA
+       AGLOBL
+       AGOK
+       AHISTORY
+       ANAME
+       ARET
+       ATEXT
+       AWORD
+       ADYNT_
+       AINIT_
+       ABCASE
+       ACASE
+       AEND
+       AMULL
+       AMULAL
+       AMULLU
+       AMULALU
+       ABX
+       ABXRET
+       ADWORD
+       ASIGNAME
+       ALDREX
+       ASTREX
+       ALDREXD
+       ASTREXD
+       APLD
+       AUNDEF
+       ACLZ
+       AMULWT
+       AMULWB
+       AMULAWT
+       AMULAWB
+       AUSEFIELD
+       ATYPE
+       AFUNCDATA
+       APCDATA
+       ACHECKNIL
+       AVARDEF
+       AVARKILL
+       ADUFFCOPY
+       ADUFFZERO
+       ADATABUNDLE
+       ADATABUNDLEEND
+       AMRC
+       ALAST
+)
+
+/* scond byte */
+const (
+       C_SCOND      = (1 << 4) - 1
+       C_SBIT       = 1 << 4
+       C_PBIT       = 1 << 5
+       C_WBIT       = 1 << 6
+       C_FBIT       = 1 << 7
+       C_UBIT       = 1 << 7
+       C_SCOND_EQ   = 0
+       C_SCOND_NE   = 1
+       C_SCOND_HS   = 2
+       C_SCOND_LO   = 3
+       C_SCOND_MI   = 4
+       C_SCOND_PL   = 5
+       C_SCOND_VS   = 6
+       C_SCOND_VC   = 7
+       C_SCOND_HI   = 8
+       C_SCOND_LS   = 9
+       C_SCOND_GE   = 10
+       C_SCOND_LT   = 11
+       C_SCOND_GT   = 12
+       C_SCOND_LE   = 13
+       C_SCOND_NONE = 14
+       C_SCOND_NV   = 15
+       SHIFT_LL     = 0 << 5
+       SHIFT_LR     = 1 << 5
+       SHIFT_AR     = 2 << 5
+       SHIFT_RR     = 3 << 5
+)
+
+const (
+       D_GOK     = 0
+       D_NONE    = 1
+       D_BRANCH  = D_NONE + 1
+       D_OREG    = D_NONE + 2
+       D_CONST   = D_NONE + 7
+       D_FCONST  = D_NONE + 8
+       D_SCONST  = D_NONE + 9
+       D_PSR     = D_NONE + 10
+       D_REG     = D_NONE + 12
+       D_FREG    = D_NONE + 13
+       D_FILE    = D_NONE + 16
+       D_OCONST  = D_NONE + 17
+       D_FILE1   = D_NONE + 18
+       D_SHIFT   = D_NONE + 19
+       D_FPCR    = D_NONE + 20
+       D_REGREG  = D_NONE + 21
+       D_ADDR    = D_NONE + 22
+       D_SBIG    = D_NONE + 23
+       D_CONST2  = D_NONE + 24
+       D_REGREG2 = D_NONE + 25
+       D_EXTERN  = D_NONE + 3
+       D_STATIC  = D_NONE + 4
+       D_AUTO    = D_NONE + 5
+       D_PARAM   = D_NONE + 6
+       D_LAST    = D_NONE + 26
+)
+
+/*
+ * this is the ranlib header
+ */
+var SYMDEF string
diff --git a/src/cmd/internal/obj/arm/anames5.go b/src/cmd/internal/obj/arm/anames5.go
new file mode 100644 (file)
index 0000000..dd7b12a
--- /dev/null
@@ -0,0 +1,196 @@
+package arm
+
+var Anames = []string{
+       "XXX",
+       "AND",
+       "EOR",
+       "SUB",
+       "RSB",
+       "ADD",
+       "ADC",
+       "SBC",
+       "RSC",
+       "TST",
+       "TEQ",
+       "CMP",
+       "CMN",
+       "ORR",
+       "BIC",
+       "MVN",
+       "B",
+       "BL",
+       "BEQ",
+       "BNE",
+       "BCS",
+       "BHS",
+       "BCC",
+       "BLO",
+       "BMI",
+       "BPL",
+       "BVS",
+       "BVC",
+       "BHI",
+       "BLS",
+       "BGE",
+       "BLT",
+       "BGT",
+       "BLE",
+       "MOVWD",
+       "MOVWF",
+       "MOVDW",
+       "MOVFW",
+       "MOVFD",
+       "MOVDF",
+       "MOVF",
+       "MOVD",
+       "CMPF",
+       "CMPD",
+       "ADDF",
+       "ADDD",
+       "SUBF",
+       "SUBD",
+       "MULF",
+       "MULD",
+       "DIVF",
+       "DIVD",
+       "SQRTF",
+       "SQRTD",
+       "ABSF",
+       "ABSD",
+       "SRL",
+       "SRA",
+       "SLL",
+       "MULU",
+       "DIVU",
+       "MUL",
+       "DIV",
+       "MOD",
+       "MODU",
+       "MOVB",
+       "MOVBS",
+       "MOVBU",
+       "MOVH",
+       "MOVHS",
+       "MOVHU",
+       "MOVW",
+       "MOVM",
+       "SWPBU",
+       "SWPW",
+       "NOP",
+       "RFE",
+       "SWI",
+       "MULA",
+       "DATA",
+       "GLOBL",
+       "GOK",
+       "HISTORY",
+       "NAME",
+       "RET",
+       "TEXT",
+       "WORD",
+       "DYNT_",
+       "INIT_",
+       "BCASE",
+       "CASE",
+       "END",
+       "MULL",
+       "MULAL",
+       "MULLU",
+       "MULALU",
+       "BX",
+       "BXRET",
+       "DWORD",
+       "SIGNAME",
+       "LDREX",
+       "STREX",
+       "LDREXD",
+       "STREXD",
+       "PLD",
+       "UNDEF",
+       "CLZ",
+       "MULWT",
+       "MULWB",
+       "MULAWT",
+       "MULAWB",
+       "USEFIELD",
+       "TYPE",
+       "FUNCDATA",
+       "PCDATA",
+       "CHECKNIL",
+       "VARDEF",
+       "VARKILL",
+       "DUFFCOPY",
+       "DUFFZERO",
+       "DATABUNDLE",
+       "DATABUNDLEEND",
+       "MRC",
+       "LAST",
+}
+
+var cnames5 = []string{
+       "NONE",
+       "REG",
+       "REGREG",
+       "REGREG2",
+       "SHIFT",
+       "FREG",
+       "PSR",
+       "FCR",
+       "RCON",
+       "NCON",
+       "SCON",
+       "LCON",
+       "LCONADDR",
+       "ZFCON",
+       "SFCON",
+       "LFCON",
+       "RACON",
+       "LACON",
+       "SBRA",
+       "LBRA",
+       "HAUTO",
+       "FAUTO",
+       "HFAUTO",
+       "SAUTO",
+       "LAUTO",
+       "HOREG",
+       "FOREG",
+       "HFOREG",
+       "SOREG",
+       "ROREG",
+       "SROREG",
+       "LOREG",
+       "PC",
+       "SP",
+       "HREG",
+       "ADDR",
+       "GOK",
+       "NCLASS",
+       "SCOND = (1<<4)-1",
+       "SBIT = 1<<4",
+       "PBIT = 1<<5",
+       "WBIT = 1<<6",
+       "FBIT = 1<<7",
+       "UBIT = 1<<7",
+       "SCOND_EQ = 0",
+       "SCOND_NE = 1",
+       "SCOND_HS = 2",
+       "SCOND_LO = 3",
+       "SCOND_MI = 4",
+       "SCOND_PL = 5",
+       "SCOND_VS = 6",
+       "SCOND_VC = 7",
+       "SCOND_HI = 8",
+       "SCOND_LS = 9",
+       "SCOND_GE = 10",
+       "SCOND_LT = 11",
+       "SCOND_GT = 12",
+       "SCOND_LE = 13",
+       "SCOND_NONE = 14",
+       "SCOND_NV = 15",
+}
+
+var dnames5 = []string{
+       D_GOK:  "GOK",
+       D_NONE: "NONE",
+}
diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go
new file mode 100644 (file)
index 0000000..54155c9
--- /dev/null
@@ -0,0 +1,3003 @@
+// Inferno utils/5l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/span.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.
+
+package arm
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+       "log"
+       "math"
+       "sort"
+)
+
+type Optab struct {
+       as       uint8
+       a1       uint8
+       a2       int8
+       a3       uint8
+       type_    uint8
+       size     int8
+       param    int8
+       flag     int8
+       pcrelsiz uint8
+}
+
+type Oprang struct {
+       start []Optab
+       stop  []Optab
+}
+
+type Opcross [32][2][32]uint8
+
+const (
+       LFROM  = 1 << 0
+       LTO    = 1 << 1
+       LPOOL  = 1 << 2
+       LPCREL = 1 << 3
+)
+
+var optab = []Optab{
+       /* struct Optab:
+       OPCODE, from, prog->reg, to,             type,size,param,flag */
+       Optab{ATEXT, C_ADDR, C_NONE, C_LCON, 0, 0, 0, 0, 0},
+       Optab{ATEXT, C_ADDR, C_REG, C_LCON, 0, 0, 0, 0, 0},
+       Optab{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
+       Optab{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+       Optab{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+       Optab{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
+       Optab{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
+       Optab{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+       Optab{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+       Optab{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+       Optab{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
+       Optab{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
+       Optab{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+       Optab{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+       Optab{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
+       Optab{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
+       Optab{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
+       Optab{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+       Optab{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
+       Optab{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+       Optab{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
+       Optab{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+       Optab{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+       Optab{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
+       Optab{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
+       Optab{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
+       Optab{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
+       Optab{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
+       Optab{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
+       Optab{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
+       Optab{ASWI, C_NONE, C_NONE, C_LOREG, 10, 4, 0, 0, 0},
+       Optab{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
+       Optab{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
+       Optab{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
+       Optab{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
+       Optab{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
+       Optab{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
+       Optab{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
+       Optab{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
+       Optab{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+       Optab{AMVN, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+       Optab{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
+       Optab{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
+       Optab{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+       Optab{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+       Optab{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+       Optab{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+       Optab{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+       Optab{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
+       Optab{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
+       Optab{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
+       Optab{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
+       Optab{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
+       Optab{AMULA, C_REG, C_REG, C_REGREG2, 17, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+       Optab{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+       Optab{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+       Optab{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+       Optab{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+       Optab{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+       Optab{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+       Optab{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+       Optab{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
+       Optab{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
+       Optab{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
+       Optab{AMOVM, C_LCON, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
+       Optab{AMOVM, C_SOREG, C_NONE, C_LCON, 39, 4, 0, 0, 0},
+       Optab{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
+       Optab{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
+       Optab{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
+       Optab{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
+       Optab{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
+       Optab{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
+       Optab{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+       Optab{AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0, 0, 0},
+       Optab{AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
+       Optab{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
+       Optab{AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+       Optab{AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+       Optab{AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+       Optab{AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+       Optab{AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+       Optab{AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+       Optab{ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0, LPCREL, 8},
+       Optab{ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0, LPCREL, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+       Optab{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+       Optab{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+       Optab{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+       Optab{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+       Optab{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+       Optab{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+       Optab{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+       Optab{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+       Optab{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+       Optab{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+       Optab{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+       Optab{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+       Optab{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+       Optab{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+       Optab{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+       Optab{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+       Optab{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+       Optab{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+       Optab{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+       Optab{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+       Optab{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+       Optab{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+       Optab{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+       Optab{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+       Optab{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+       Optab{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+       Optab{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+       Optab{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+       Optab{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+       Optab{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+       Optab{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+       Optab{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
+       Optab{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
+       Optab{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
+       Optab{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
+       Optab{ACMPF, C_FREG, C_REG, C_NONE, 82, 8, 0, 0, 0},
+       Optab{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
+       Optab{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
+       Optab{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
+       Optab{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
+       Optab{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
+       Optab{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
+       Optab{ATST, C_REG, C_NONE, C_NONE, 90, 4, 0, 0, 0},
+       Optab{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
+       Optab{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
+       Optab{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
+       Optab{AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
+       Optab{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
+       Optab{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
+       Optab{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
+       Optab{AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+       Optab{APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
+       Optab{AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
+       Optab{ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+       Optab{ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+       Optab{ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+
+       Optab{ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
+       Optab{ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
+       Optab{AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
+}
+
+var pool struct {
+       start uint32
+       size  uint32
+       extra uint32
+}
+
+var oprange [ALAST]Oprang
+
+var xcmp [C_GOK + 1][C_GOK + 1]uint8
+
+var zprg = obj.Prog{
+       As:    AGOK,
+       Scond: C_SCOND_NONE,
+       Reg:   NREG,
+       From: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+       To: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+}
+
+var deferreturn *obj.LSym
+
+func nocache(p *obj.Prog) {
+       p.Optab = 0
+       p.From.Class = 0
+       p.To.Class = 0
+}
+
+/* size of a case statement including jump table */
+func casesz(ctxt *obj.Link, p *obj.Prog) int32 {
+
+       var jt int = 0
+       var n int32 = 0
+       var o *Optab
+
+       for ; p != nil; p = p.Link {
+               if p.As == ABCASE {
+                       jt = 1
+               } else if jt != 0 {
+                       break
+               }
+               o = oplook(ctxt, p)
+               n += int32(o.size)
+       }
+
+       return n
+}
+
+// asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
+// It returns the total number of bytes put in out, and it can change
+// p->pc if extra padding is necessary.
+// In rare cases, asmoutnacl might split p into two instructions.
+// origPC is the PC for this Prog (no padding is taken into account).
+func asmoutnacl(ctxt *obj.Link, origPC int32, p *obj.Prog, o *Optab, out []uint32) int {
+
+       var size int
+       var reg int
+       var q *obj.Prog
+       var a *obj.Addr
+       var a2 *obj.Addr
+
+       size = int(o.size)
+
+       // instruction specific
+       switch p.As {
+
+       default:
+               if out != nil {
+                       asmout(ctxt, p, o, out)
+               }
+
+       case ADATABUNDLE, // align to 16-byte boundary
+               ADATABUNDLEEND: // zero width instruction, just to align next instruction to 16-byte boundary
+               p.Pc = (p.Pc + 15) &^ 15
+
+               if out != nil {
+                       asmout(ctxt, p, o, out)
+               }
+
+       case AUNDEF,
+               APLD:
+               size = 4
+               if out != nil {
+                       switch p.As {
+                       case AUNDEF:
+                               out[0] = 0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
+
+                       case APLD:
+                               out[0] = 0xe1a01001 // (MOVW R1, R1)
+                               break
+                       }
+               }
+
+       case AB,
+               ABL:
+               if p.To.Type != D_OREG {
+                       if out != nil {
+                               asmout(ctxt, p, o, out)
+                       }
+               } else {
+
+                       if p.To.Offset != 0 || size != 4 || p.To.Reg >= 16 || p.To.Reg < 0 {
+                               ctxt.Diag("unsupported instruction: %v", p)
+                       }
+                       if p.Pc&15 == 12 {
+                               p.Pc += 4
+                       }
+                       if out != nil {
+                               out[0] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03c0013f | uint32(p.To.Reg)<<12 | uint32(p.To.Reg)<<16 // BIC $0xc000000f, Rx
+                               if p.As == AB {
+                                       out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff10 | uint32(p.To.Reg) // BX Rx // ABL
+                               } else {
+                                       out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff30 | uint32(p.To.Reg) // BLX Rx
+                               }
+                       }
+
+                       size = 8
+               }
+
+               // align the last instruction (the actual BL) to the last instruction in a bundle
+               if p.As == ABL {
+
+                       if deferreturn == nil {
+                               deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+                       }
+                       if p.To.Sym == deferreturn {
+                               p.Pc = ((int64(origPC) + 15) &^ 15) + 16 - int64(size)
+                       } else {
+
+                               p.Pc += (16 - ((p.Pc + int64(size)) & 15)) & 15
+                       }
+               }
+
+       case ALDREX,
+               ALDREXD,
+               AMOVB,
+               AMOVBS,
+               AMOVBU,
+               AMOVD,
+               AMOVF,
+               AMOVH,
+               AMOVHS,
+               AMOVHU,
+               AMOVM,
+               AMOVW,
+               ASTREX,
+               ASTREXD:
+               if p.To.Type == D_REG && p.To.Reg == 15 && p.From.Reg == 13 { // MOVW.W x(R13), PC
+                       if out != nil {
+                               asmout(ctxt, p, o, out)
+                       }
+                       if size == 4 {
+                               if out != nil {
+                                       // Note: 5c and 5g reg.c know that DIV/MOD smashes R12
+                                       // so that this return instruction expansion is valid.
+                                       out[0] = out[0] &^ 0x3000                           // change PC to R12
+                                       out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
+                                       out[2] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff1c // BX R12
+                               }
+
+                               size += 8
+                               if (p.Pc+int64(size))&15 == 4 {
+                                       p.Pc += 4
+                               }
+                               break
+                       } else {
+
+                               // if the instruction used more than 4 bytes, then it must have used a very large
+                               // offset to update R13, so we need to additionally mask R13.
+                               if out != nil {
+
+                                       out[size/4-1] &^= 0x3000                                   // change PC to R12
+                                       out[size/4] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03cdd103   // BIC $0xc0000000, R13
+                                       out[size/4+1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
+                                       out[size/4+2] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff1c // BX R12
+                               }
+
+                               // p->pc+size is only ok at 4 or 12 mod 16.
+                               if (p.Pc+int64(size))%8 == 0 {
+
+                                       p.Pc += 4
+                               }
+                               size += 12
+                               break
+                       }
+               }
+
+               if p.To.Type == D_REG && p.To.Reg == 15 {
+                       ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p)
+               }
+
+               if p.To.Type == D_OREG && p.To.Reg == 13 && (p.Scond&C_WBIT != 0) && size > 4 {
+                       // function prolog with very large frame size: MOVW.W R14,-100004(R13)
+                       // split it into two instructions:
+                       //      ADD $-100004, R13
+                       //      MOVW R14, 0(R13)
+                       q = ctxt.NewProg()
+
+                       p.Scond &^= C_WBIT
+                       *q = *p
+                       a = &p.To
+                       if p.To.Type == D_OREG {
+                               a2 = &q.To
+                       } else {
+
+                               a2 = &q.From
+                       }
+                       nocache(q)
+                       nocache(p)
+
+                       // insert q after p
+                       q.Link = p.Link
+
+                       p.Link = q
+                       q.Pcond = nil
+
+                       // make p into ADD $X, R13
+                       p.As = AADD
+
+                       p.From = *a
+                       p.From.Reg = NREG
+                       p.From.Type = D_CONST
+                       p.To = zprg.To
+                       p.To.Type = D_REG
+                       p.To.Reg = 13
+
+                       // make q into p but load/store from 0(R13)
+                       q.Spadj = 0
+
+                       *a2 = zprg.From
+                       a2.Type = D_OREG
+                       a2.Reg = 13
+                       a2.Sym = nil
+                       a2.Offset = 0
+                       size = int(oplook(ctxt, p).size)
+                       break
+               }
+
+               if (p.To.Type == D_OREG && p.To.Reg != 13 && p.To.Reg != 9) || (p.From.Type == D_OREG && p.From.Reg != 13 && p.From.Reg != 9) { // MOVW Rx, X(Ry), y != 13 && y != 9 // MOVW X(Rx), Ry, x != 13 && x != 9
+                       if p.To.Type == D_OREG {
+                               a = &p.To
+                       } else {
+
+                               a = &p.From
+                       }
+                       reg = int(a.Reg)
+                       if size == 4 {
+                               // if addr.reg == NREG, then it is probably load from x(FP) with small x, no need to modify.
+                               if reg == NREG {
+
+                                       if out != nil {
+                                               asmout(ctxt, p, o, out)
+                                       }
+                               } else {
+
+                                       if out != nil {
+                                               out[0] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03c00103 | uint32(reg)<<16 | uint32(reg)<<12 // BIC $0xc0000000, Rx
+                                       }
+                                       if p.Pc&15 == 12 {
+                                               p.Pc += 4
+                                       }
+                                       size += 4
+                                       if out != nil {
+                                               asmout(ctxt, p, o, out[1:])
+                                       }
+                               }
+
+                               break
+                       } else {
+
+                               // if a load/store instruction takes more than 1 word to implement, then
+                               // we need to seperate the instruction into two:
+                               // 1. explicitly load the address into R11.
+                               // 2. load/store from R11.
+                               // This won't handle .W/.P, so we should reject such code.
+                               if p.Scond&(C_PBIT|C_WBIT) != 0 {
+
+                                       ctxt.Diag("unsupported instruction (.P/.W): %v", p)
+                               }
+                               q = ctxt.NewProg()
+                               *q = *p
+                               if p.To.Type == D_OREG {
+                                       a2 = &q.To
+                               } else {
+
+                                       a2 = &q.From
+                               }
+                               nocache(q)
+                               nocache(p)
+
+                               // insert q after p
+                               q.Link = p.Link
+
+                               p.Link = q
+                               q.Pcond = nil
+
+                               // make p into MOVW $X(R), R11
+                               p.As = AMOVW
+
+                               p.From = *a
+                               p.From.Type = D_CONST
+                               p.To = zprg.To
+                               p.To.Type = D_REG
+                               p.To.Reg = 11
+
+                               // make q into p but load/store from 0(R11)
+                               *a2 = zprg.From
+
+                               a2.Type = D_OREG
+                               a2.Reg = 11
+                               a2.Sym = nil
+                               a2.Offset = 0
+                               size = int(oplook(ctxt, p).size)
+                               break
+                       }
+               } else if out != nil {
+                       asmout(ctxt, p, o, out)
+               }
+               break
+       }
+
+       // destination register specific
+       if p.To.Type == D_REG {
+
+               switch p.To.Reg {
+               case 9:
+                       ctxt.Diag("invalid instruction, cannot write to R9: %v", p)
+
+               case 13:
+                       if out != nil {
+                               out[size/4] = 0xe3cdd103 // BIC $0xc0000000, R13
+                       }
+                       if (p.Pc+int64(size))&15 == 0 {
+                               p.Pc += 4
+                       }
+                       size += 4
+                       break
+               }
+       }
+
+       return size
+}
+
+func span5(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var op *obj.Prog
+       var o *Optab
+       var m int
+       var bflag int
+       var i int
+       var v int
+       var times int
+       var c int32
+       var opc int32
+       var out [6 + 3]uint32
+       var bp []byte
+
+       p = cursym.Text
+       if p == nil || p.Link == nil { // handle external functions and ELF section symbols
+               return
+       }
+
+       if oprange[AAND].start == nil {
+               buildop(ctxt)
+       }
+
+       ctxt.Cursym = cursym
+
+       ctxt.Autosize = int32(p.To.Offset + 4)
+       c = 0
+
+       op = p
+       p = p.Link
+       for ; p != nil || ctxt.Blitrl != nil; (func() { op = p; p = p.Link })() {
+               if p == nil {
+                       if checkpool(ctxt, op, 0) != 0 {
+                               p = op
+                               continue
+                       }
+
+                       // can't happen: blitrl is not nil, but checkpool didn't flushpool
+                       ctxt.Diag("internal inconsistency")
+
+                       break
+               }
+
+               ctxt.Curp = p
+               p.Pc = int64(c)
+               o = oplook(ctxt, p)
+               if ctxt.Headtype != obj.Hnacl {
+                       m = int(o.size)
+               } else {
+
+                       m = asmoutnacl(ctxt, c, p, o, nil)
+                       c = int32(p.Pc)     // asmoutnacl might change pc for alignment
+                       o = oplook(ctxt, p) // asmoutnacl might change p in rare cases
+               }
+
+               if m%4 != 0 || p.Pc%4 != 0 {
+                       ctxt.Diag("!pc invalid: %v size=%d", p, m)
+               }
+
+               // must check literal pool here in case p generates many instructions
+               if ctxt.Blitrl != nil {
+
+                       i = m
+                       if p.As == ACASE {
+                               i = int(casesz(ctxt, p))
+                       }
+                       if checkpool(ctxt, op, i) != 0 {
+                               p = op
+                               continue
+                       }
+               }
+
+               if m == 0 && (p.As != AFUNCDATA && p.As != APCDATA && p.As != ADATABUNDLEEND && p.As != ANOP) {
+                       ctxt.Diag("zero-width instruction\n%v", p)
+                       continue
+               }
+
+               switch o.flag & (LFROM | LTO | LPOOL) {
+               case LFROM:
+                       addpool(ctxt, p, &p.From)
+
+               case LTO:
+                       addpool(ctxt, p, &p.To)
+
+               case LPOOL:
+                       if p.Scond&C_SCOND == C_SCOND_NONE {
+                               flushpool(ctxt, p, 0, 0)
+                       }
+                       break
+               }
+
+               if p.As == AMOVW && p.To.Type == D_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
+                       flushpool(ctxt, p, 0, 0)
+               }
+               c += int32(m)
+       }
+
+       cursym.Size = int64(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.
+        */
+       times = 0
+
+       for {
+               if ctxt.Debugvlog != 0 {
+                       fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+               }
+               bflag = 0
+               c = 0
+               times++
+               cursym.Text.Pc = 0 // force re-layout the code.
+               for p = cursym.Text; p != nil; p = p.Link {
+                       ctxt.Curp = p
+                       o = oplook(ctxt, p)
+                       if int64(c) > p.Pc {
+                               p.Pc = int64(c)
+                       }
+
+                       /* very large branches
+                       if(o->type == 6 && p->pcond) {
+                               otxt = p->pcond->pc - c;
+                               if(otxt < 0)
+                                       otxt = -otxt;
+                               if(otxt >= (1L<<17) - 10) {
+                                       q = ctxt->arch->prg();
+                                       q->link = p->link;
+                                       p->link = q;
+                                       q->as = AB;
+                                       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 = AB;
+                                       q->to.type = D_BRANCH;
+                                       q->pcond = q->link->link;
+                                       bflag = 1;
+                               }
+                       }
+                       */
+                       opc = int32(p.Pc)
+
+                       if ctxt.Headtype != obj.Hnacl {
+                               m = int(o.size)
+                       } else {
+
+                               m = asmoutnacl(ctxt, c, p, o, nil)
+                       }
+                       if p.Pc != int64(opc) {
+                               bflag = 1
+                       }
+
+                       //print("%P pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
+                       c = int32(p.Pc + int64(m))
+
+                       if m%4 != 0 || p.Pc%4 != 0 {
+                               ctxt.Diag("pc invalid: %v size=%d", p, m)
+                       }
+
+                       if m/4 > len(out) {
+                               ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
+                       }
+                       if m == 0 && (p.As != AFUNCDATA && p.As != APCDATA && p.As != ADATABUNDLEEND && p.As != ANOP) {
+                               if p.As == ATEXT {
+                                       ctxt.Autosize = int32(p.To.Offset + 4)
+                                       continue
+                               }
+
+                               ctxt.Diag("zero-width instruction\n%v", p)
+                               continue
+                       }
+               }
+
+               cursym.Size = int64(c)
+               if !(bflag != 0) {
+                       break
+               }
+       }
+
+       if c%4 != 0 {
+               ctxt.Diag("sym->size=%d, invalid", c)
+       }
+
+       /*
+        * lay out the code.  all the pc-relative code references,
+        * even cross-function, are resolved now;
+        * only data references need to be relocated.
+        * with more work we could leave cross-function
+        * code references to be relocated too, and then
+        * perhaps we'd be able to parallelize the span loop above.
+        */
+       if ctxt.Tlsg == nil {
+
+               ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+       }
+
+       p = cursym.Text
+       ctxt.Autosize = int32(p.To.Offset + 4)
+       obj.Symgrow(ctxt, cursym, cursym.Size)
+
+       bp = cursym.P
+       c = int32(p.Pc) // even p->link might need extra padding
+       for p = p.Link; p != nil; p = p.Link {
+               ctxt.Pc = p.Pc
+               ctxt.Curp = p
+               o = oplook(ctxt, p)
+               opc = int32(p.Pc)
+               if ctxt.Headtype != obj.Hnacl {
+                       asmout(ctxt, p, o, out[:])
+                       m = int(o.size)
+               } else {
+
+                       m = asmoutnacl(ctxt, c, p, o, out[:])
+                       if int64(opc) != p.Pc {
+                               ctxt.Diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %v", opc, int32(p.Pc), p)
+                       }
+               }
+
+               if m%4 != 0 || p.Pc%4 != 0 {
+                       ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
+               }
+
+               if int64(c) > p.Pc {
+                       ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, c, p)
+               }
+               for int64(c) != p.Pc {
+                       // emit 0xe1a00000 (MOVW R0, R0)
+                       bp[0] = 0x00
+                       bp = bp[1:]
+
+                       bp[0] = 0x00
+                       bp = bp[1:]
+                       bp[0] = 0xa0
+                       bp = bp[1:]
+                       bp[0] = 0xe1
+                       bp = bp[1:]
+                       c += 4
+               }
+
+               for i = 0; i < m/4; i++ {
+                       v = int(out[i])
+                       bp[0] = byte(v)
+                       bp = bp[1:]
+                       bp[0] = byte(v >> 8)
+                       bp = bp[1:]
+                       bp[0] = byte(v >> 16)
+                       bp = bp[1:]
+                       bp[0] = byte(v >> 24)
+                       bp = bp[1:]
+               }
+
+               c += int32(m)
+       }
+}
+
+/*
+ * when the first reference to the literal pool threatens
+ * to go out of range of a 12-bit PC-relative offset,
+ * drop the pool now, and branch round it.
+ * this happens only in extended basic blocks that exceed 4k.
+ */
+func checkpool(ctxt *obj.Link, p *obj.Prog, sz int) int {
+
+       if pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+pool.size)-int64(pool.start+8))) == 0 {
+               return flushpool(ctxt, p, 1, 0)
+       } else if p.Link == nil {
+               return flushpool(ctxt, p, 2, 0)
+       }
+       return 0
+}
+
+func flushpool(ctxt *obj.Link, p *obj.Prog, skip int, force int) int {
+       var q *obj.Prog
+
+       if ctxt.Blitrl != nil {
+               if skip != 0 {
+                       if false && skip == 1 {
+                               fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), pool.size, pool.start)
+                       }
+                       q = ctxt.NewProg()
+                       q.As = AB
+                       q.To.Type = D_BRANCH
+                       q.Pcond = p.Link
+                       q.Link = ctxt.Blitrl
+                       q.Lineno = p.Lineno
+                       ctxt.Blitrl = q
+               } else if !(force != 0) && (p.Pc+int64(12+pool.size)-int64(pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size
+                       return 0
+               }
+               if ctxt.Headtype == obj.Hnacl && pool.size%16 != 0 {
+                       // if pool is not multiple of 16 bytes, add an alignment marker
+                       q = ctxt.NewProg()
+
+                       q.As = ADATABUNDLEEND
+                       ctxt.Elitrl.Link = q
+                       ctxt.Elitrl = q
+               }
+
+               ctxt.Elitrl.Link = p.Link
+               p.Link = ctxt.Blitrl
+
+               // BUG(minux): how to correctly handle line number for constant pool entries?
+               // for now, we set line number to the last instruction preceding them at least
+               // this won't bloat the .debug_line tables
+               for ctxt.Blitrl != nil {
+
+                       ctxt.Blitrl.Lineno = p.Lineno
+                       ctxt.Blitrl = ctxt.Blitrl.Link
+               }
+
+               ctxt.Blitrl = nil /* BUG: should refer back to values until out-of-range */
+               ctxt.Elitrl = nil
+               pool.size = 0
+               pool.start = 0
+               pool.extra = 0
+               return 1
+       }
+
+       return 0
+}
+
+func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+       var q *obj.Prog
+       var t obj.Prog
+       var c int
+
+       c = aclass(ctxt, a)
+
+       t = zprg
+       t.As = AWORD
+
+       switch c {
+       default:
+               t.To.Offset = a.Offset
+               t.To.Sym = a.Sym
+               t.To.Type = a.Type
+               t.To.Name = a.Name
+
+               if ctxt.Flag_shared != 0 && t.To.Sym != nil {
+                       t.Pcrel = p
+               }
+
+       case C_SROREG,
+               C_LOREG,
+               C_ROREG,
+               C_FOREG,
+               C_SOREG,
+               C_HOREG,
+               C_FAUTO,
+               C_SAUTO,
+               C_LAUTO,
+               C_LACON:
+               t.To.Type = D_CONST
+               t.To.Offset = ctxt.Instoffset
+               break
+       }
+
+       if t.Pcrel == nil {
+               for q = ctxt.Blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
+                       if q.Pcrel == nil && q.To == t.To {
+                               p.Pcond = q
+                               return
+                       }
+               }
+       }
+
+       if ctxt.Headtype == obj.Hnacl && pool.size%16 == 0 {
+               // start a new data bundle
+               q = ctxt.NewProg()
+
+               *q = zprg
+               q.As = ADATABUNDLE
+               q.Pc = int64(pool.size)
+               pool.size += 4
+               if ctxt.Blitrl == nil {
+                       ctxt.Blitrl = q
+                       pool.start = uint32(p.Pc)
+               } else {
+
+                       ctxt.Elitrl.Link = q
+               }
+
+               ctxt.Elitrl = q
+       }
+
+       q = ctxt.NewProg()
+       *q = t
+       q.Pc = int64(pool.size)
+
+       if ctxt.Blitrl == nil {
+               ctxt.Blitrl = q
+               pool.start = uint32(p.Pc)
+       } else {
+
+               ctxt.Elitrl.Link = q
+       }
+       ctxt.Elitrl = q
+       pool.size += 4
+
+       p.Pcond = q
+}
+
+func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
+       ctxt.Instoffset = 0
+       aclass(ctxt, a)
+       return int32(ctxt.Instoffset)
+}
+
+func immrot(v uint32) int32 {
+       var i int
+
+       for i = 0; i < 16; i++ {
+               if v&^0xff == 0 {
+                       return int32(uint32(int32(i)<<8) | v | 1<<25)
+               }
+               v = v<<2 | v>>30
+       }
+
+       return 0
+}
+
+func immaddr(v int32) int32 {
+       if v >= 0 && v <= 0xfff {
+               return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
+       }
+       if v >= -0xfff && v < 0 {
+               return -v&0xfff | 1<<24 /* pre indexing */
+       }
+       return 0
+}
+
+func immfloat(v int32) bool {
+       return v&0xC03 == 0 /* offset will fit in floating-point load/store */
+}
+
+func immhalf(v int32) bool {
+       if v >= 0 && v <= 0xff {
+               return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
+       }
+       if v >= -0xff && v < 0 {
+               return -v&0xff|1<<24 != 0 /* pre indexing */
+       }
+       return false
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+       var s *obj.LSym
+       var t int
+
+       switch a.Type {
+       case D_NONE:
+               return C_NONE
+
+       case D_REG:
+               return C_REG
+
+       case D_REGREG:
+               return C_REGREG
+
+       case D_REGREG2:
+               return C_REGREG2
+
+       case D_SHIFT:
+               return C_SHIFT
+
+       case D_FREG:
+               return C_FREG
+
+       case D_FPCR:
+               return C_FCR
+
+       case D_OREG:
+               switch a.Name {
+               case D_EXTERN,
+                       D_STATIC:
+                       if a.Sym == nil || a.Sym.Name == "" {
+                               fmt.Printf("null sym external\n")
+                               return C_GOK
+                       }
+
+                       ctxt.Instoffset = 0 // s.b. unused but just in case
+                       return C_ADDR
+
+               case D_AUTO:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+                       t = int(immaddr(int32(ctxt.Instoffset)))
+                       if t != 0 {
+                               if immhalf(int32(ctxt.Instoffset)) {
+                                       if immfloat(int32(t)) {
+                                               return C_HFAUTO
+                                       }
+                                       return C_HAUTO
+                               }
+
+                               if immfloat(int32(t)) {
+                                       return C_FAUTO
+                               }
+                               return C_SAUTO
+                       }
+
+                       return C_LAUTO
+
+               case D_PARAM:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4
+                       t = int(immaddr(int32(ctxt.Instoffset)))
+                       if t != 0 {
+                               if immhalf(int32(ctxt.Instoffset)) {
+                                       if immfloat(int32(t)) {
+                                               return C_HFAUTO
+                                       }
+                                       return C_HAUTO
+                               }
+
+                               if immfloat(int32(t)) {
+                                       return C_FAUTO
+                               }
+                               return C_SAUTO
+                       }
+
+                       return C_LAUTO
+
+               case D_NONE:
+                       ctxt.Instoffset = a.Offset
+                       t = int(immaddr(int32(ctxt.Instoffset)))
+                       if t != 0 {
+                               if immhalf(int32(ctxt.Instoffset)) { /* n.b. that it will also satisfy immrot */
+                                       if immfloat(int32(t)) {
+                                               return C_HFOREG
+                                       }
+                                       return C_HOREG
+                               }
+
+                               if immfloat(int32(t)) {
+                                       return C_FOREG /* n.b. that it will also satisfy immrot */
+                               }
+                               t = int(immrot(uint32(ctxt.Instoffset)))
+                               if t != 0 {
+                                       return C_SROREG
+                               }
+                               if immhalf(int32(ctxt.Instoffset)) {
+                                       return C_HOREG
+                               }
+                               return C_SOREG
+                       }
+
+                       t = int(immrot(uint32(ctxt.Instoffset)))
+                       if t != 0 {
+                               return C_ROREG
+                       }
+                       return C_LOREG
+               }
+
+               return C_GOK
+
+       case D_PSR:
+               return C_PSR
+
+       case D_OCONST:
+               switch a.Name {
+               case D_EXTERN,
+                       D_STATIC:
+                       ctxt.Instoffset = 0 // s.b. unused but just in case
+                       return C_ADDR
+               }
+
+               return C_GOK
+
+       case D_FCONST:
+               if chipzero5(ctxt, a.U.Dval) >= 0 {
+                       return C_ZFCON
+               }
+               if chipfloat5(ctxt, a.U.Dval) >= 0 {
+                       return C_SFCON
+               }
+               return C_LFCON
+
+       case D_CONST,
+               D_CONST2:
+               switch a.Name {
+               case D_NONE:
+                       ctxt.Instoffset = a.Offset
+                       if a.Reg != NREG {
+                               return aconsize(ctxt)
+                       }
+
+                       t = int(immrot(uint32(ctxt.Instoffset)))
+                       if t != 0 {
+                               return C_RCON
+                       }
+                       t = int(immrot(uint32(^ctxt.Instoffset)))
+                       if t != 0 {
+                               return C_NCON
+                       }
+                       return C_LCON
+
+               case D_EXTERN,
+                       D_STATIC:
+                       s = a.Sym
+                       if s == nil {
+                               break
+                       }
+                       ctxt.Instoffset = 0 // s.b. unused but just in case
+                       return C_LCONADDR
+
+               case D_AUTO:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+                       return aconsize(ctxt)
+
+               case D_PARAM:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4
+                       return aconsize(ctxt)
+               }
+
+               return C_GOK
+
+       case D_BRANCH:
+               return C_SBRA
+       }
+
+       return C_GOK
+}
+
+func aconsize(ctxt *obj.Link) int {
+       var t int
+
+       t = int(immrot(uint32(ctxt.Instoffset)))
+       if t != 0 {
+               return C_RACON
+       }
+       return C_LACON
+}
+
+func prasm(p *obj.Prog) {
+       fmt.Printf("%v\n", p)
+}
+
+func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+       var a1 int
+       var a2 int
+       var a3 int
+       var r int
+       var c1 []byte
+       var c3 []byte
+       var o []Optab
+       var e []Optab
+
+       a1 = int(p.Optab)
+       if a1 != 0 {
+               return &optab[a1-1:][0]
+       }
+       a1 = int(p.From.Class)
+       if a1 == 0 {
+               a1 = aclass(ctxt, &p.From) + 1
+               p.From.Class = int8(a1)
+       }
+
+       a1--
+       a3 = int(p.To.Class)
+       if a3 == 0 {
+               a3 = aclass(ctxt, &p.To) + 1
+               p.To.Class = int8(a3)
+       }
+
+       a3--
+       a2 = C_NONE
+       if p.Reg != NREG {
+               a2 = C_REG
+       }
+       r = int(p.As)
+       o = oprange[r].start
+       if o == nil {
+               o = oprange[r].stop /* just generate an error */
+       }
+
+       if false { /*debug['O']*/
+               fmt.Printf("oplook %v %v %v %v\n", Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
+               fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
+       }
+
+       e = oprange[r].stop
+       c1 = xcmp[a1][:]
+       c3 = xcmp[a3][:]
+       for ; -cap(o) < -cap(e); o = o[1:] {
+               if int(o[0].a2) == a2 {
+                       if c1[o[0].a1] != 0 {
+                               if c3[o[0].a3] != 0 {
+                                       p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+                                       return &o[0]
+                               }
+                       }
+               }
+       }
+
+       ctxt.Diag("illegal combination %v; %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type)
+       ctxt.Diag("from %d %d to %d %d\n", p.From.Type, p.From.Name, p.To.Type, p.To.Name)
+       prasm(p)
+       if o == nil {
+               o = optab
+       }
+       return &o[0]
+}
+
+func cmp(a int, b int) bool {
+       if a == b {
+               return true
+       }
+       switch a {
+       case C_LCON:
+               if b == C_RCON || b == C_NCON {
+                       return true
+               }
+
+       case C_LACON:
+               if b == C_RACON {
+                       return true
+               }
+
+       case C_LFCON:
+               if b == C_ZFCON || b == C_SFCON {
+                       return true
+               }
+
+       case C_HFAUTO:
+               return b == C_HAUTO || b == C_FAUTO
+
+       case C_FAUTO,
+               C_HAUTO:
+               return b == C_HFAUTO
+
+       case C_SAUTO:
+               return cmp(C_HFAUTO, b)
+
+       case C_LAUTO:
+               return cmp(C_SAUTO, b)
+
+       case C_HFOREG:
+               return b == C_HOREG || b == C_FOREG
+
+       case C_FOREG,
+               C_HOREG:
+               return b == C_HFOREG
+
+       case C_SROREG:
+               return cmp(C_SOREG, b) || cmp(C_ROREG, b)
+
+       case C_SOREG,
+               C_ROREG:
+               return b == C_SROREG || cmp(C_HFOREG, b)
+
+       case C_LOREG:
+               return cmp(C_SROREG, b)
+
+       case C_LBRA:
+               if b == C_SBRA {
+                       return true
+               }
+
+       case C_HREG:
+               return cmp(C_SP, b) || cmp(C_PC, b)
+       }
+
+       return false
+}
+
+type ocmp []Optab
+
+func (x ocmp) Len() int {
+       return len(x)
+}
+
+func (x ocmp) Swap(i, j int) {
+       x[i], x[j] = x[j], x[i]
+}
+
+func (x ocmp) Less(i, j int) bool {
+       var p1 *Optab
+       var p2 *Optab
+       var n int
+
+       p1 = &x[i]
+       p2 = &x[j]
+       n = int(p1.as) - int(p2.as)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a1) - int(p2.a1)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a2) - int(p2.a2)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a3) - int(p2.a3)
+       if n != 0 {
+               return n < 0
+       }
+       return false
+}
+
+func buildop(ctxt *obj.Link) {
+       var i int
+       var n int
+       var r int
+
+       for i = 0; i < C_GOK; i++ {
+               for n = 0; n < C_GOK; n++ {
+                       if cmp(n, i) {
+                               xcmp[i][n] = 1
+                       }
+               }
+       }
+       for n = 0; optab[n].as != AXXX; n++ {
+               if optab[n].flag&LPCREL != 0 {
+                       if ctxt.Flag_shared != 0 {
+                               optab[n].size += int8(optab[n].pcrelsiz)
+                       } else {
+
+                               optab[n].flag &^= LPCREL
+                       }
+               }
+       }
+
+       sort.Sort(ocmp(optab[:n]))
+       for i = 0; i < n; i++ {
+               r = int(optab[i].as)
+               oprange[r].start = optab[i:]
+               for int(optab[i].as) == r {
+                       i++
+               }
+               oprange[r].stop = optab[i:]
+               i--
+
+               switch r {
+               default:
+                       ctxt.Diag("unknown op in build: %v", Aconv(r))
+                       log.Fatalf("bad code")
+
+               case AADD:
+                       oprange[AAND] = oprange[r]
+                       oprange[AEOR] = oprange[r]
+                       oprange[ASUB] = oprange[r]
+                       oprange[ARSB] = oprange[r]
+                       oprange[AADC] = oprange[r]
+                       oprange[ASBC] = oprange[r]
+                       oprange[ARSC] = oprange[r]
+                       oprange[AORR] = oprange[r]
+                       oprange[ABIC] = oprange[r]
+
+               case ACMP:
+                       oprange[ATEQ] = oprange[r]
+                       oprange[ACMN] = oprange[r]
+
+               case AMVN:
+                       break
+
+               case ABEQ:
+                       oprange[ABNE] = oprange[r]
+                       oprange[ABCS] = oprange[r]
+                       oprange[ABHS] = oprange[r]
+                       oprange[ABCC] = oprange[r]
+                       oprange[ABLO] = oprange[r]
+                       oprange[ABMI] = oprange[r]
+                       oprange[ABPL] = oprange[r]
+                       oprange[ABVS] = oprange[r]
+                       oprange[ABVC] = oprange[r]
+                       oprange[ABHI] = oprange[r]
+                       oprange[ABLS] = oprange[r]
+                       oprange[ABGE] = oprange[r]
+                       oprange[ABLT] = oprange[r]
+                       oprange[ABGT] = oprange[r]
+                       oprange[ABLE] = oprange[r]
+
+               case ASLL:
+                       oprange[ASRL] = oprange[r]
+                       oprange[ASRA] = oprange[r]
+
+               case AMUL:
+                       oprange[AMULU] = oprange[r]
+
+               case ADIV:
+                       oprange[AMOD] = oprange[r]
+                       oprange[AMODU] = oprange[r]
+                       oprange[ADIVU] = oprange[r]
+
+               case AMOVW,
+                       AMOVB,
+                       AMOVBS,
+                       AMOVBU,
+                       AMOVH,
+                       AMOVHS,
+                       AMOVHU:
+                       break
+
+               case ASWPW:
+                       oprange[ASWPBU] = oprange[r]
+
+               case AB,
+                       ABL,
+                       ABX,
+                       ABXRET,
+                       ADUFFZERO,
+                       ADUFFCOPY,
+                       ASWI,
+                       AWORD,
+                       AMOVM,
+                       ARFE,
+                       ATEXT,
+                       AUSEFIELD,
+                       ACASE,
+                       ABCASE,
+                       ATYPE:
+                       break
+
+               case AADDF:
+                       oprange[AADDD] = oprange[r]
+                       oprange[ASUBF] = oprange[r]
+                       oprange[ASUBD] = oprange[r]
+                       oprange[AMULF] = oprange[r]
+                       oprange[AMULD] = oprange[r]
+                       oprange[ADIVF] = oprange[r]
+                       oprange[ADIVD] = oprange[r]
+                       oprange[ASQRTF] = oprange[r]
+                       oprange[ASQRTD] = oprange[r]
+                       oprange[AMOVFD] = oprange[r]
+                       oprange[AMOVDF] = oprange[r]
+                       oprange[AABSF] = oprange[r]
+                       oprange[AABSD] = oprange[r]
+
+               case ACMPF:
+                       oprange[ACMPD] = oprange[r]
+
+               case AMOVF:
+                       oprange[AMOVD] = oprange[r]
+
+               case AMOVFW:
+                       oprange[AMOVDW] = oprange[r]
+
+               case AMOVWF:
+                       oprange[AMOVWD] = oprange[r]
+
+               case AMULL:
+                       oprange[AMULAL] = oprange[r]
+                       oprange[AMULLU] = oprange[r]
+                       oprange[AMULALU] = oprange[r]
+
+               case AMULWT:
+                       oprange[AMULWB] = oprange[r]
+
+               case AMULAWT:
+                       oprange[AMULAWB] = oprange[r]
+
+               case AMULA,
+                       ALDREX,
+                       ASTREX,
+                       ALDREXD,
+                       ASTREXD,
+                       ATST,
+                       APLD,
+                       AUNDEF,
+                       ACLZ,
+                       AFUNCDATA,
+                       APCDATA,
+                       ANOP,
+                       ADATABUNDLE,
+                       ADATABUNDLEEND:
+                       break
+               }
+       }
+}
+
+func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
+       var o1 uint32
+       var o2 uint32
+       var o3 uint32
+       var o4 uint32
+       var o5 uint32
+       var o6 uint32
+       var v int32
+       var r int
+       var rf int
+       var rt int
+       var rt2 int
+       var rel *obj.Reloc
+
+       ctxt.Printp = p
+       o1 = 0
+       o2 = 0
+       o3 = 0
+       o4 = 0
+       o5 = 0
+       o6 = 0
+       ctxt.Armsize += int32(o.size)
+       if false { /*debug['P']*/
+               fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
+       }
+       switch o.type_ {
+       default:
+               ctxt.Diag("unknown asm %d", o.type_)
+               prasm(p)
+
+       case 0: /* pseudo ops */
+               if false { /*debug['G']*/
+                       fmt.Printf("%x: %s: arm %d\n", uint32(p.Pc), p.From.Sym.Name, p.From.Sym.Fnptr)
+               }
+
+       case 1: /* op R,[R],R */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               rf = int(p.From.Reg)
+               rt = int(p.To.Reg)
+               r = int(p.Reg)
+               if p.To.Type == D_NONE {
+                       rt = 0
+               }
+               if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
+                       r = 0
+               } else if r == NREG {
+                       r = rt
+               }
+               o1 |= uint32(rf) | uint32(r)<<16 | uint32(rt)<<12
+
+       case 2: /* movbu $I,[R],R */
+               aclass(ctxt, &p.From)
+
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+               o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+               rt = int(p.To.Reg)
+               r = int(p.Reg)
+               if p.To.Type == D_NONE {
+                       rt = 0
+               }
+               if p.As == AMOVW || p.As == AMVN {
+                       r = 0
+               } else if r == NREG {
+                       r = rt
+               }
+               o1 |= uint32(r)<<16 | uint32(rt)<<12
+
+       case 3: /* add R<<[IR],[R],R */
+               o1 = mov(ctxt, p)
+
+       case 4: /* add $I,[R],R */
+               aclass(ctxt, &p.From)
+
+               o1 = oprrr(ctxt, AADD, int(p.Scond))
+               o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 |= uint32(r) << 16
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 5: /* bra s */
+               o1 = opbra(ctxt, int(p.As), int(p.Scond))
+
+               v = -8
+               if p.To.Sym != nil {
+                       rel = obj.Addrel(ctxt.Cursym)
+                       rel.Off = int32(ctxt.Pc)
+                       rel.Siz = 4
+                       rel.Sym = p.To.Sym
+                       v += int32(p.To.Offset)
+                       rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
+                       rel.Type = obj.R_CALLARM
+                       break
+               }
+
+               if p.Pcond != nil {
+                       v = int32((p.Pcond.Pc - ctxt.Pc) - 8)
+               }
+               o1 |= (uint32(v) >> 2) & 0xffffff
+
+       case 6: /* b ,O(R) -> add $O,R,PC */
+               aclass(ctxt, &p.To)
+
+               o1 = oprrr(ctxt, AADD, int(p.Scond))
+               o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+               o1 |= uint32(p.To.Reg) << 16
+               o1 |= REGPC << 12
+
+       case 7: /* bl (R) -> blx R */
+               aclass(ctxt, &p.To)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("%v: doesn't support BL offset(REG) where offset != 0", p)
+               }
+               o1 = oprrr(ctxt, ABL, int(p.Scond))
+               o1 |= uint32(p.To.Reg)
+               rel = obj.Addrel(ctxt.Cursym)
+               rel.Off = int32(ctxt.Pc)
+               rel.Siz = 0
+               rel.Type = obj.R_CALLIND
+
+       case 8: /* sll $c,[R],R -> mov (R<<$c),R */
+               aclass(ctxt, &p.From)
+
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 |= uint32(r)
+               o1 |= uint32((ctxt.Instoffset & 31) << 7)
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 9: /* sll R,[R],R -> mov (R<<R),R */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 |= uint32(r)
+               o1 |= uint32(p.From.Reg)<<8 | 1<<4
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 10: /* swi [$con] */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               if p.To.Type != D_NONE {
+                       aclass(ctxt, &p.To)
+                       o1 |= uint32(ctxt.Instoffset & 0xffffff)
+               }
+
+       case 11: /* word */
+               aclass(ctxt, &p.To)
+
+               o1 = uint32(ctxt.Instoffset)
+               if p.To.Sym != nil {
+                       // This case happens with words generated
+                       // in the PC stream as part of the literal pool.
+                       rel = obj.Addrel(ctxt.Cursym)
+
+                       rel.Off = int32(ctxt.Pc)
+                       rel.Siz = 4
+                       rel.Sym = p.To.Sym
+                       rel.Add = p.To.Offset
+
+                       // runtime.tlsg is special.
+                       // Its "address" is the offset from the TLS thread pointer
+                       // to the thread-local g and m pointers.
+                       // Emit a TLS relocation instead of a standard one.
+                       if rel.Sym == ctxt.Tlsg {
+
+                               rel.Type = obj.R_TLS
+                               if ctxt.Flag_shared != 0 {
+                                       rel.Add += ctxt.Pc - p.Pcrel.Pc - 8 - int64(rel.Siz)
+                               }
+                               rel.Xadd = rel.Add
+                               rel.Xsym = rel.Sym
+                       } else if ctxt.Flag_shared != 0 {
+                               rel.Type = obj.R_PCREL
+                               rel.Add += ctxt.Pc - p.Pcrel.Pc - 8
+                       } else {
+
+                               rel.Type = obj.R_ADDR
+                       }
+                       o1 = 0
+               }
+
+       case 12: /* movw $lcon, reg */
+               o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+
+               if o.flag&LPCREL != 0 {
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(p.To.Reg) | REGPC<<16 | uint32(p.To.Reg)<<12
+               }
+
+       case 13: /* op $lcon, [R], R */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = oprrr(ctxt, int(p.As), int(p.Scond))
+               o2 |= REGTMP
+               r = int(p.Reg)
+               if p.As == AMOVW || p.As == AMVN {
+                       r = 0
+               } else if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o2 |= uint32(r) << 16
+               if p.To.Type != D_NONE {
+                       o2 |= uint32(p.To.Reg) << 12
+               }
+
+       case 14: /* movb/movbu/movh/movhu R,R */
+               o1 = oprrr(ctxt, ASLL, int(p.Scond))
+
+               if p.As == AMOVBU || p.As == AMOVHU {
+                       o2 = oprrr(ctxt, ASRL, int(p.Scond))
+               } else {
+
+                       o2 = oprrr(ctxt, ASRA, int(p.Scond))
+               }
+
+               r = int(p.To.Reg)
+               o1 |= uint32(p.From.Reg) | uint32(r)<<12
+               o2 |= uint32(r) | uint32(r)<<12
+               if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
+                       o1 |= 24 << 7
+                       o2 |= 24 << 7
+               } else {
+
+                       o1 |= 16 << 7
+                       o2 |= 16 << 7
+               }
+
+       case 15: /* mul r,[r,]r */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               rf = int(p.From.Reg)
+               rt = int(p.To.Reg)
+               r = int(p.Reg)
+               if r == NREG {
+                       r = rt
+               }
+               if rt == r {
+                       r = rf
+                       rf = rt
+               }
+
+               if false {
+                       if rt == r || rf == REGPC || r == REGPC || rt == REGPC {
+                               ctxt.Diag("bad registers in MUL")
+                               prasm(p)
+                       }
+               }
+
+               o1 |= uint32(rf)<<8 | uint32(r) | uint32(rt)<<16
+
+       case 16: /* div r,[r,]r */
+               o1 = 0xf << 28
+
+               o2 = 0
+
+       case 17:
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+               rf = int(p.From.Reg)
+               rt = int(p.To.Reg)
+               rt2 = int(p.To.Offset)
+               r = int(p.Reg)
+               o1 |= uint32(rf)<<8 | uint32(r) | uint32(rt)<<16 | uint32(rt2)<<12
+
+       case 20: /* mov/movb/movbu R,O(R) */
+               aclass(ctxt, &p.To)
+
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = osr(ctxt, int(p.As), int(p.From.Reg), int32(ctxt.Instoffset), r, int(p.Scond))
+
+       case 21: /* mov/movbu O(R),R -> lr */
+               aclass(ctxt, &p.From)
+
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = olr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond))
+               if p.As != AMOVW {
+                       o1 |= 1 << 22
+               }
+
+       case 30: /* mov/movb/movbu R,L(R) */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = osrr(ctxt, int(p.From.Reg), REGTMP, r, int(p.Scond))
+               if p.As != AMOVW {
+                       o2 |= 1 << 22
+               }
+
+       case 31: /* mov/movbu L(R),R -> lr[b] */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = olrr(ctxt, REGTMP, r, int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
+                       o2 |= 1 << 22
+               }
+
+       case 34: /* mov $lacon,R */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+
+               o2 = oprrr(ctxt, AADD, int(p.Scond))
+               o2 |= REGTMP
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 |= uint32(r) << 16
+               if p.To.Type != D_NONE {
+                       o2 |= uint32(p.To.Reg) << 12
+               }
+
+       case 35: /* mov PSR,R */
+               o1 = 2<<23 | 0xf<<16 | 0<<0
+
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+               o1 |= (uint32(p.From.Reg) & 1) << 22
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 36: /* mov R,PSR */
+               o1 = 2<<23 | 0x29f<<12 | 0<<4
+
+               if p.Scond&C_FBIT != 0 {
+                       o1 ^= 0x010 << 12
+               }
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+               o1 |= (uint32(p.To.Reg) & 1) << 22
+               o1 |= uint32(p.From.Reg) << 0
+
+       case 37: /* mov $con,PSR */
+               aclass(ctxt, &p.From)
+
+               o1 = 2<<23 | 0x29f<<12 | 0<<4
+               if p.Scond&C_FBIT != 0 {
+                       o1 ^= 0x010 << 12
+               }
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+               o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+               o1 |= (uint32(p.To.Reg) & 1) << 22
+               o1 |= uint32(p.From.Reg) << 0
+
+       case 38,
+               39:
+               switch o.type_ {
+               case 38: /* movm $con,oreg -> stm */
+                       o1 = 0x4 << 25
+
+                       o1 |= uint32(p.From.Offset & 0xffff)
+                       o1 |= uint32(p.To.Reg) << 16
+                       aclass(ctxt, &p.To)
+
+               case 39: /* movm oreg,$con -> ldm */
+                       o1 = 0x4<<25 | 1<<20
+
+                       o1 |= uint32(p.To.Offset & 0xffff)
+                       o1 |= uint32(p.From.Reg) << 16
+                       aclass(ctxt, &p.From)
+                       break
+               }
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in MOVM; %v", p)
+               }
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+               if p.Scond&C_PBIT != 0 {
+                       o1 |= 1 << 24
+               }
+               if p.Scond&C_UBIT != 0 {
+                       o1 |= 1 << 23
+               }
+               if p.Scond&C_SBIT != 0 {
+                       o1 |= 1 << 22
+               }
+               if p.Scond&C_WBIT != 0 {
+                       o1 |= 1 << 21
+               }
+
+       case 40: /* swp oreg,reg,reg */
+               aclass(ctxt, &p.From)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in SWP")
+               }
+               o1 = 0x2<<23 | 0x9<<4
+               if p.As != ASWPW {
+                       o1 |= 1 << 22
+               }
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.Reg) << 0
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
+               o1 = 0xe8fd8000
+
+       case 50: /* floating point store */
+               v = regoff(ctxt, &p.To)
+
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = ofsr(ctxt, int(p.As), int(p.From.Reg), v, r, int(p.Scond), p)
+
+       case 51: /* floating point load */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = ofsr(ctxt, int(p.As), int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
+
+       case 52: /* floating point store, int32 offset UGLY */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP<<12 | REGTMP<<16 | uint32(r)
+               o3 = ofsr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
+
+       case 53: /* floating point load, int32 offset UGLY */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP<<12 | REGTMP<<16 | uint32(r)
+               o3 = ofsr(ctxt, int(p.As), int(p.To.Reg), 0, REGTMP, int(p.Scond), p) | 1<<20
+
+       case 54: /* floating point arith */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               rf = int(p.From.Reg)
+               rt = int(p.To.Reg)
+               r = int(p.Reg)
+               if r == NREG {
+                       r = rt
+                       if p.As == AMOVF || p.As == AMOVD || p.As == AMOVFD || p.As == AMOVDF || p.As == ASQRTF || p.As == ASQRTD || p.As == AABSF || p.As == AABSD {
+                               r = 0
+                       }
+               }
+
+               o1 |= uint32(rf) | uint32(r)<<16 | uint32(rt)<<12
+
+       case 56: /* move to FP[CS]R */
+               o1 = (uint32(p.Scond)&C_SCOND)<<28 | 0xe<<24 | 1<<8 | 1<<4
+
+               o1 |= (uint32(p.To.Reg)+1)<<21 | uint32(p.From.Reg)<<12
+
+       case 57: /* move from FP[CS]R */
+               o1 = (uint32(p.Scond)&C_SCOND)<<28 | 0xe<<24 | 1<<8 | 1<<4
+
+               o1 |= (uint32(p.From.Reg)+1)<<21 | uint32(p.To.Reg)<<12 | 1<<20
+
+       case 58: /* movbu R,R */
+               o1 = oprrr(ctxt, AAND, int(p.Scond))
+
+               o1 |= uint32(immrot(0xff))
+               rt = int(p.To.Reg)
+               r = int(p.From.Reg)
+               if p.To.Type == D_NONE {
+                       rt = 0
+               }
+               if r == NREG {
+                       r = rt
+               }
+               o1 |= uint32(r)<<16 | uint32(rt)<<12
+
+       case 59: /* movw/bu R<<I(R),R -> ldr indexed */
+               if p.From.Reg == NREG {
+
+                       if p.As != AMOVW {
+                               ctxt.Diag("byte MOV from shifter operand")
+                       }
+                       o1 = mov(ctxt, p)
+                       break
+               }
+
+               if p.From.Offset&(1<<4) != 0 {
+                       ctxt.Diag("bad shift in LDR")
+               }
+               o1 = olrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVBU {
+                       o1 |= 1 << 22
+               }
+
+       case 60: /* movb R(R),R -> ldrsb indexed */
+               if p.From.Reg == NREG {
+
+                       ctxt.Diag("byte MOV from shifter operand")
+                       o1 = mov(ctxt, p)
+                       break
+               }
+
+               if p.From.Offset&(^0xf) != 0 {
+                       ctxt.Diag("bad shift in LDRSB")
+               }
+               o1 = olhrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
+               o1 ^= 1<<5 | 1<<6
+
+       case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
+               if p.To.Reg == NREG {
+
+                       ctxt.Diag("MOV to shifter operand")
+               }
+               o1 = osrr(ctxt, int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
+                       o1 |= 1 << 22
+               }
+
+       case 62: /* case R -> movw      R<<2(PC),PC */
+               if o.flag&LPCREL != 0 {
+
+                       o1 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(immrot(1)) | uint32(p.From.Reg)<<16 | REGTMP<<12
+                       o2 = olrr(ctxt, REGTMP, REGPC, REGTMP, int(p.Scond))
+                       o2 |= 2 << 7
+                       o3 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGPC<<12
+               } else {
+
+                       o1 = olrr(ctxt, int(p.From.Reg), REGPC, REGPC, int(p.Scond))
+                       o1 |= 2 << 7
+               }
+
+       case 63: /* bcase */
+               if p.Pcond != nil {
+
+                       rel = obj.Addrel(ctxt.Cursym)
+                       rel.Off = int32(ctxt.Pc)
+                       rel.Siz = 4
+                       if p.To.Sym != nil && p.To.Sym.Type != 0 {
+                               rel.Sym = p.To.Sym
+                               rel.Add = p.To.Offset
+                       } else {
+
+                               rel.Sym = ctxt.Cursym
+                               rel.Add = p.Pcond.Pc
+                       }
+
+                       if o.flag&LPCREL != 0 {
+                               rel.Type = obj.R_PCREL
+                               rel.Add += ctxt.Pc - p.Pcrel.Pc - 16 + int64(rel.Siz)
+                       } else {
+
+                               rel.Type = obj.R_ADDR
+                       }
+                       o1 = 0
+               }
+
+               /* reloc ops */
+       case 64: /* mov/movb/movbu R,addr */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = osr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond))
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+       case 65: /* mov/movbu addr,R */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = olr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
+                       o2 |= 1 << 22
+               }
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+       case 68: /* floating point store -> ADDR */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = ofsr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+       case 69: /* floating point load <- ADDR */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = ofsr(ctxt, int(p.As), int(p.To.Reg), 0, REGTMP, int(p.Scond), p) | 1<<20
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+               /* ArmV4 ops: */
+       case 70: /* movh/movhu R,O(R) -> strh */
+               aclass(ctxt, &p.To)
+
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = oshr(ctxt, int(p.From.Reg), int32(ctxt.Instoffset), r, int(p.Scond))
+
+       case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
+               aclass(ctxt, &p.From)
+
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = olhr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVB || p.As == AMOVBS {
+                       o1 ^= 1<<5 | 1<<6
+               } else if p.As == AMOVH || p.As == AMOVHS {
+                       o1 ^= (1 << 6)
+               }
+
+       case 72: /* movh/movhu R,L(R) -> strh */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = oshrr(ctxt, int(p.From.Reg), REGTMP, r, int(p.Scond))
+
+       case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o2 = olhrr(ctxt, REGTMP, r, int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVB || p.As == AMOVBS {
+                       o2 ^= 1<<5 | 1<<6
+               } else if p.As == AMOVH || p.As == AMOVHS {
+                       o2 ^= (1 << 6)
+               }
+
+       case 74: /* bx $I */
+               ctxt.Diag("ABX $I")
+
+       case 75: /* bx O(R) */
+               aclass(ctxt, &p.To)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("non-zero offset in ABX")
+               }
+
+               /*
+                       o1 =    oprrr(ctxt, AADD, p->scond) | immrot(0) | (REGPC<<16) | (REGLINK<<12);  // mov PC, LR
+                       o2 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | p->to.reg;              // BX R
+               */
+               // p->to.reg may be REGLINK
+               o1 = oprrr(ctxt, AADD, int(p.Scond))
+
+               o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+               o1 |= uint32(p.To.Reg) << 16
+               o1 |= REGTMP << 12
+               o2 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(immrot(0)) | REGPC<<16 | REGLINK<<12 // mov PC, LR
+               o3 = (uint32(p.Scond)&C_SCOND)<<28 | 0x12fff<<8 | 1<<4 | REGTMP                    // BX Rtmp
+
+       case 76: /* bx O(R) when returning from fn*/
+               ctxt.Diag("ABXRET")
+
+       case 77: /* ldrex oreg,reg */
+               aclass(ctxt, &p.From)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in LDREX")
+               }
+               o1 = 0x19<<20 | 0xf9f
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 78: /* strex reg,oreg,reg */
+               aclass(ctxt, &p.From)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in STREX")
+               }
+               o1 = 0x18<<20 | 0xf90
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.Reg) << 0
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 80: /* fmov zfcon,freg */
+               if p.As == AMOVD {
+
+                       o1 = 0xeeb00b00 // VMOV imm 64
+                       o2 = oprrr(ctxt, ASUBD, int(p.Scond))
+               } else {
+
+                       o1 = 0x0eb00a00 // VMOV imm 32
+                       o2 = oprrr(ctxt, ASUBF, int(p.Scond))
+               }
+
+               v = 0x70 // 1.0
+               r = int(p.To.Reg)
+
+               // movf $1.0, r
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+               o1 |= uint32(r) << 12
+               o1 |= (uint32(v) & 0xf) << 0
+               o1 |= (uint32(v) & 0xf0) << 12
+
+               // subf r,r,r
+               o2 |= uint32(r) | uint32(r)<<16 | uint32(r)<<12
+
+       case 81: /* fmov sfcon,freg */
+               o1 = 0x0eb00a00 // VMOV imm 32
+               if p.As == AMOVD {
+                       o1 = 0xeeb00b00 // VMOV imm 64
+               }
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+               o1 |= uint32(p.To.Reg) << 12
+               v = int32(chipfloat5(ctxt, p.From.U.Dval))
+               o1 |= (uint32(v) & 0xf) << 0
+               o1 |= (uint32(v) & 0xf0) << 12
+
+       case 82: /* fcmp freg,freg, */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.Reg)<<12 | uint32(p.From.Reg)<<0
+               o2 = 0x0ef1fa10 // VMRS R15
+               o2 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 83: /* fcmp freg,, */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.From.Reg)<<12 | 1<<16
+               o2 = 0x0ef1fa10 // VMRS R15
+               o2 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 84: /* movfw freg,freg - truncate float-to-fix */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 0
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 85: /* movwf freg,freg - fix-to-float */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 0
+               o1 |= uint32(p.To.Reg) << 12
+
+               // macro for movfw freg,FTMP; movw FTMP,reg
+       case 86: /* movfw freg,reg - truncate float-to-fix */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 0
+               o1 |= FREGTMP << 12
+               o2 = oprrr(ctxt, AMOVFW+AEND, int(p.Scond))
+               o2 |= FREGTMP << 16
+               o2 |= uint32(p.To.Reg) << 12
+
+               // macro for movw reg,FTMP; movwf FTMP,freg
+       case 87: /* movwf reg,freg - fix-to-float */
+               o1 = oprrr(ctxt, AMOVWF+AEND, int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 12
+               o1 |= FREGTMP << 16
+               o2 = oprrr(ctxt, int(p.As), int(p.Scond))
+               o2 |= FREGTMP << 0
+               o2 |= uint32(p.To.Reg) << 12
+
+       case 88: /* movw reg,freg  */
+               o1 = oprrr(ctxt, AMOVWF+AEND, int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 12
+               o1 |= uint32(p.To.Reg) << 16
+
+       case 89: /* movw freg,reg  */
+               o1 = oprrr(ctxt, AMOVFW+AEND, int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.To.Reg) << 12
+
+       case 90: /* tst reg  */
+               o1 = oprrr(ctxt, ACMP+AEND, int(p.Scond))
+
+               o1 |= uint32(p.From.Reg) << 16
+
+       case 91: /* ldrexd oreg,reg */
+               aclass(ctxt, &p.From)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in LDREX")
+               }
+               o1 = 0x1b<<20 | 0xf9f
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 92: /* strexd reg,oreg,reg */
+               aclass(ctxt, &p.From)
+
+               if ctxt.Instoffset != 0 {
+                       ctxt.Diag("offset must be zero in STREX")
+               }
+               o1 = 0x1a<<20 | 0xf90
+               o1 |= uint32(p.From.Reg) << 16
+               o1 |= uint32(p.Reg) << 0
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+       case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
+               o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = olhr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond))
+               if p.As == AMOVB || p.As == AMOVBS {
+                       o2 ^= 1<<5 | 1<<6
+               } else if p.As == AMOVH || p.As == AMOVHS {
+                       o2 ^= (1 << 6)
+               }
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+       case 94: /* movh/movhu R,addr -> strh */
+               o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+               if !(o1 != 0) {
+                       break
+               }
+               o2 = oshr(ctxt, int(p.From.Reg), 0, REGTMP, int(p.Scond))
+               if o.flag&LPCREL != 0 {
+                       o3 = o2
+                       o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+               }
+
+       case 95: /* PLD off(reg) */
+               o1 = 0xf5d0f000
+
+               o1 |= uint32(p.From.Reg) << 16
+               if p.From.Offset < 0 {
+                       o1 &^= (1 << 23)
+                       o1 |= uint32((-p.From.Offset) & 0xfff)
+               } else {
+
+                       o1 |= uint32(p.From.Offset & 0xfff)
+               }
+
+               // This is supposed to be something that stops execution.
+       // It's not supposed to be reached, ever, but if it is, we'd
+       // like to be able to tell how we got there.  Assemble as
+       // 0xf7fabcfd which is guaranteed to raise undefined instruction
+       // exception.
+       case 96: /* UNDEF */
+               o1 = 0xf7fabcfd
+
+       case 97: /* CLZ Rm, Rd */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= uint32(p.From.Reg)
+
+       case 98: /* MULW{T,B} Rs, Rm, Rd */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.To.Reg) << 16
+               o1 |= uint32(p.From.Reg) << 8
+               o1 |= uint32(p.Reg)
+
+       case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
+               o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+               o1 |= uint32(p.To.Reg) << 12
+               o1 |= uint32(p.From.Reg) << 8
+               o1 |= uint32(p.Reg)
+               o1 |= uint32(p.To.Offset << 16)
+
+               // DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
+       // DATABUNDLEEND: zero width alignment marker
+       case 100:
+               if p.As == ADATABUNDLE {
+
+                       o1 = 0xe125be70
+               }
+               break
+       }
+
+       out[0] = o1
+       out[1] = o2
+       out[2] = o3
+       out[3] = o4
+       out[4] = o5
+       out[5] = o6
+       return
+}
+
+func mov(ctxt *obj.Link, p *obj.Prog) uint32 {
+       var o1 uint32
+       var rt int
+       var r int
+
+       aclass(ctxt, &p.From)
+       o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+       o1 |= uint32(p.From.Offset)
+       rt = int(p.To.Reg)
+       r = int(p.Reg)
+       if p.To.Type == D_NONE {
+               rt = 0
+       }
+       if p.As == AMOVW || p.As == AMVN {
+               r = 0
+       } else if r == NREG {
+               r = rt
+       }
+       o1 |= uint32(r)<<16 | uint32(rt)<<12
+       return o1
+}
+
+func oprrr(ctxt *obj.Link, a int, sc int) uint32 {
+       var o uint32
+
+       o = (uint32(sc) & C_SCOND) << 28
+       if sc&C_SBIT != 0 {
+               o |= 1 << 20
+       }
+       if sc&(C_PBIT|C_WBIT) != 0 {
+               ctxt.Diag(".nil/.W on dp instruction")
+       }
+       switch a {
+       case AMULU,
+               AMUL:
+               return o | 0x0<<21 | 0x9<<4
+       case AMULA:
+               return o | 0x1<<21 | 0x9<<4
+       case AMULLU:
+               return o | 0x4<<21 | 0x9<<4
+       case AMULL:
+               return o | 0x6<<21 | 0x9<<4
+       case AMULALU:
+               return o | 0x5<<21 | 0x9<<4
+       case AMULAL:
+               return o | 0x7<<21 | 0x9<<4
+       case AAND:
+               return o | 0x0<<21
+       case AEOR:
+               return o | 0x1<<21
+       case ASUB:
+               return o | 0x2<<21
+       case ARSB:
+               return o | 0x3<<21
+       case AADD:
+               return o | 0x4<<21
+       case AADC:
+               return o | 0x5<<21
+       case ASBC:
+               return o | 0x6<<21
+       case ARSC:
+               return o | 0x7<<21
+       case ATST:
+               return o | 0x8<<21 | 1<<20
+       case ATEQ:
+               return o | 0x9<<21 | 1<<20
+       case ACMP:
+               return o | 0xa<<21 | 1<<20
+       case ACMN:
+               return o | 0xb<<21 | 1<<20
+       case AORR:
+               return o | 0xc<<21
+
+       case AMOVB,
+               AMOVH,
+               AMOVW:
+               return o | 0xd<<21
+       case ABIC:
+               return o | 0xe<<21
+       case AMVN:
+               return o | 0xf<<21
+       case ASLL:
+               return o | 0xd<<21 | 0<<5
+       case ASRL:
+               return o | 0xd<<21 | 1<<5
+       case ASRA:
+               return o | 0xd<<21 | 2<<5
+       case ASWI:
+               return o | 0xf<<24
+
+       case AADDD:
+               return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
+       case AADDF:
+               return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
+       case ASUBD:
+               return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
+       case ASUBF:
+               return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
+       case AMULD:
+               return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
+       case AMULF:
+               return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
+       case ADIVD:
+               return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
+       case ADIVF:
+               return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
+       case ASQRTD:
+               return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
+       case ASQRTF:
+               return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
+       case AABSD:
+               return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
+       case AABSF:
+               return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
+       case ACMPD:
+               return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
+       case ACMPF:
+               return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
+
+       case AMOVF:
+               return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
+       case AMOVD:
+               return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
+
+       case AMOVDF:
+               return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
+       case AMOVFD:
+               return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
+
+       case AMOVWF:
+               if sc&C_UBIT == 0 {
+
+                       o |= 1 << 7 /* signed */
+               }
+               return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
+
+       case AMOVWD:
+               if sc&C_UBIT == 0 {
+                       o |= 1 << 7 /* signed */
+               }
+               return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
+
+       case AMOVFW:
+               if sc&C_UBIT == 0 {
+
+                       o |= 1 << 16 /* signed */
+               }
+               return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
+
+       case AMOVDW:
+               if sc&C_UBIT == 0 {
+                       o |= 1 << 16 /* signed */
+               }
+               return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
+
+       case AMOVWF + AEND: // copy WtoF
+               return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
+
+       case AMOVFW + AEND: // copy FtoW
+               return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
+
+       case ACMP + AEND: // cmp imm
+               return o | 0x3<<24 | 0x5<<20
+
+               // CLZ doesn't support .nil
+       case ACLZ:
+               return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
+
+       case AMULWT:
+               return o&(0xf<<28) | 0x12<<20 | 0xe<<4
+
+       case AMULWB:
+               return o&(0xf<<28) | 0x12<<20 | 0xa<<4
+
+       case AMULAWT:
+               return o&(0xf<<28) | 0x12<<20 | 0xc<<4
+
+       case AMULAWB:
+               return o&(0xf<<28) | 0x12<<20 | 0x8<<4
+
+       case ABL: // BLX REG
+               return o&(0xf<<28) | 0x12fff3<<4
+       }
+
+       ctxt.Diag("bad rrr %d", a)
+       prasm(ctxt.Curp)
+       return 0
+}
+
+func opbra(ctxt *obj.Link, a int, sc int) uint32 {
+       if sc&(C_SBIT|C_PBIT|C_WBIT) != 0 {
+               ctxt.Diag(".nil/.nil/.W on bra instruction")
+       }
+       sc &= C_SCOND
+       if a == ABL || a == ADUFFZERO || a == ADUFFCOPY {
+               return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
+       }
+       if sc != 0xe {
+               ctxt.Diag(".COND on bcond instruction")
+       }
+       switch a {
+       case ABEQ:
+               return 0x0<<28 | 0x5<<25
+       case ABNE:
+               return 0x1<<28 | 0x5<<25
+       case ABCS:
+               return 0x2<<28 | 0x5<<25
+       case ABHS:
+               return 0x2<<28 | 0x5<<25
+       case ABCC:
+               return 0x3<<28 | 0x5<<25
+       case ABLO:
+               return 0x3<<28 | 0x5<<25
+       case ABMI:
+               return 0x4<<28 | 0x5<<25
+       case ABPL:
+               return 0x5<<28 | 0x5<<25
+       case ABVS:
+               return 0x6<<28 | 0x5<<25
+       case ABVC:
+               return 0x7<<28 | 0x5<<25
+       case ABHI:
+               return 0x8<<28 | 0x5<<25
+       case ABLS:
+               return 0x9<<28 | 0x5<<25
+       case ABGE:
+               return 0xa<<28 | 0x5<<25
+       case ABLT:
+               return 0xb<<28 | 0x5<<25
+       case ABGT:
+               return 0xc<<28 | 0x5<<25
+       case ABLE:
+               return 0xd<<28 | 0x5<<25
+       case AB:
+               return 0xe<<28 | 0x5<<25
+       }
+
+       ctxt.Diag("bad bra %v", Aconv(a))
+       prasm(ctxt.Curp)
+       return 0
+}
+
+func olr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 {
+       var o uint32
+
+       if sc&C_SBIT != 0 {
+               ctxt.Diag(".nil on LDR/STR instruction")
+       }
+       o = (uint32(sc) & C_SCOND) << 28
+       if !(sc&C_PBIT != 0) {
+               o |= 1 << 24
+       }
+       if !(sc&C_UBIT != 0) {
+               o |= 1 << 23
+       }
+       if sc&C_WBIT != 0 {
+               o |= 1 << 21
+       }
+       o |= 1<<26 | 1<<20
+       if v < 0 {
+               if sc&C_UBIT != 0 {
+                       ctxt.Diag(".U on neg offset")
+               }
+               v = -v
+               o ^= 1 << 23
+       }
+
+       if v >= 1<<12 || v < 0 {
+               ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp)
+       }
+       o |= uint32(v)
+       o |= uint32(b) << 16
+       o |= uint32(r) << 12
+       return o
+}
+
+func olhr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 {
+       var o uint32
+
+       if sc&C_SBIT != 0 {
+               ctxt.Diag(".nil on LDRH/STRH instruction")
+       }
+       o = (uint32(sc) & C_SCOND) << 28
+       if !(sc&C_PBIT != 0) {
+               o |= 1 << 24
+       }
+       if sc&C_WBIT != 0 {
+               o |= 1 << 21
+       }
+       o |= 1<<23 | 1<<20 | 0xb<<4
+       if v < 0 {
+               v = -v
+               o ^= 1 << 23
+       }
+
+       if v >= 1<<8 || v < 0 {
+               ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp)
+       }
+       o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
+       o |= uint32(b) << 16
+       o |= uint32(r) << 12
+       return o
+}
+
+func osr(ctxt *obj.Link, a int, r int, v int32, b int, sc int) uint32 {
+       var o uint32
+
+       o = olr(ctxt, v, b, r, sc) ^ (1 << 20)
+       if a != AMOVW {
+               o |= 1 << 22
+       }
+       return o
+}
+
+func oshr(ctxt *obj.Link, r int, v int32, b int, sc int) uint32 {
+       var o uint32
+
+       o = olhr(ctxt, v, b, r, sc) ^ (1 << 20)
+       return o
+}
+
+func osrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 {
+       return olr(ctxt, int32(i), b, r, sc) ^ (1<<25 | 1<<20)
+}
+
+func oshrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 {
+       return olhr(ctxt, int32(i), b, r, sc) ^ (1<<22 | 1<<20)
+}
+
+func olrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 {
+       return olr(ctxt, int32(i), b, r, sc) ^ (1 << 25)
+}
+
+func olhrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 {
+       return olhr(ctxt, int32(i), b, r, sc) ^ (1 << 22)
+}
+
+func ofsr(ctxt *obj.Link, a int, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
+       var o uint32
+
+       if sc&C_SBIT != 0 {
+               ctxt.Diag(".nil on FLDR/FSTR instruction")
+       }
+       o = (uint32(sc) & C_SCOND) << 28
+       if !(sc&C_PBIT != 0) {
+               o |= 1 << 24
+       }
+       if sc&C_WBIT != 0 {
+               o |= 1 << 21
+       }
+       o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
+       if v < 0 {
+               v = -v
+               o ^= 1 << 23
+       }
+
+       if v&3 != 0 {
+               ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
+       } else if v >= 1<<10 || v < 0 {
+               ctxt.Diag("literal span too large: %d\n%v", v, p)
+       }
+       o |= (uint32(v) >> 2) & 0xFF
+       o |= uint32(b) << 16
+       o |= uint32(r) << 12
+
+       switch a {
+       default:
+               ctxt.Diag("bad fst %v", Aconv(a))
+               fallthrough
+
+       case AMOVD:
+               o |= 1 << 8
+               fallthrough
+
+       case AMOVF:
+               break
+       }
+
+       return o
+}
+
+func omvl(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, dr int) uint32 {
+       var v int32
+       var o1 uint32
+       if !(p.Pcond != nil) {
+               aclass(ctxt, a)
+               v = immrot(uint32(^ctxt.Instoffset))
+               if v == 0 {
+                       ctxt.Diag("missing literal")
+                       prasm(p)
+                       return 0
+               }
+
+               o1 = oprrr(ctxt, AMVN, int(p.Scond)&C_SCOND)
+               o1 |= uint32(v)
+               o1 |= uint32(dr) << 12
+       } else {
+
+               v = int32(p.Pcond.Pc - p.Pc - 8)
+               o1 = olr(ctxt, v, REGPC, dr, int(p.Scond)&C_SCOND)
+       }
+
+       return o1
+}
+
+func chipzero5(ctxt *obj.Link, e float64) int {
+       // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+       if ctxt.Goarm < 7 || e != 0 {
+
+               return -1
+       }
+       return 0
+}
+
+func chipfloat5(ctxt *obj.Link, e float64) int {
+       var n int
+       var h1 uint32
+       var l uint32
+       var h uint32
+       var ei uint64
+
+       // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+       if ctxt.Goarm < 7 {
+
+               goto no
+       }
+
+       ei = math.Float64bits(e)
+       l = uint32(ei)
+       h = uint32(ei >> 32)
+
+       if l != 0 || h&0xffff != 0 {
+               goto no
+       }
+       h1 = h & 0x7fc00000
+       if h1 != 0x40000000 && h1 != 0x3fc00000 {
+               goto no
+       }
+       n = 0
+
+       // sign bit (a)
+       if h&0x80000000 != 0 {
+
+               n |= 1 << 7
+       }
+
+       // exp sign bit (b)
+       if h1 == 0x3fc00000 {
+
+               n |= 1 << 6
+       }
+
+       // rest of exp and mantissa (cd-efgh)
+       n |= int((h >> 16) & 0x3f)
+
+       //print("match %.8lux %.8lux %d\n", l, h, n);
+       return n
+
+no:
+       return -1
+}
diff --git a/src/cmd/internal/obj/arm/list5.go b/src/cmd/internal/obj/arm/list5.go
new file mode 100644 (file)
index 0000000..ee9e53e
--- /dev/null
@@ -0,0 +1,311 @@
+// Inferno utils/5c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.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.
+
+package arm
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+)
+
+const (
+       STRINGSZ = 1000
+)
+
+var extra = []string{
+       ".EQ",
+       ".NE",
+       ".CS",
+       ".CC",
+       ".MI",
+       ".PL",
+       ".VS",
+       ".VC",
+       ".HI",
+       ".LS",
+       ".GE",
+       ".LT",
+       ".GT",
+       ".LE",
+       "",
+       ".NV",
+}
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+       var str string
+       var sc string
+       var fp string
+
+       var a int
+       var s int
+
+       a = int(p.As)
+       s = int(p.Scond)
+       sc = extra[s&C_SCOND]
+       if s&C_SBIT != 0 {
+               sc += ".S"
+       }
+       if s&C_PBIT != 0 {
+               sc += ".P"
+       }
+       if s&C_WBIT != 0 {
+               sc += ".W"
+       }
+       if s&C_UBIT != 0 { /* ambiguous with FBIT */
+               sc += ".U"
+       }
+       if a == AMOVM {
+               if p.From.Type == D_CONST {
+                       str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, RAconv(&p.From), Dconv(p, 0, &p.To))
+               } else if p.To.Type == D_CONST {
+                       str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), RAconv(&p.To))
+               } else {
+
+                       str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+               }
+       } else if a == ADATA {
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+       } else if p.As == ATEXT {
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+       } else if p.Reg == NREG {
+               str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+       } else if p.From.Type != D_FREG {
+               str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,R%d,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+       } else {
+
+               str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,F%d,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+       }
+
+       fp += str
+       return fp
+}
+
+func Aconv(a int) string {
+       var s string
+       var fp string
+
+       s = "???"
+       if a >= AXXX && a < ALAST {
+               s = Anames[a]
+       }
+       fp += s
+       return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+       var str string
+       var fp string
+
+       var op string
+       var v int
+
+       switch a.Type {
+       default:
+               str = fmt.Sprintf("GOK-type(%d)", a.Type)
+
+       case D_NONE:
+               str = ""
+               if a.Name != D_NONE || a.Reg != NREG || a.Sym != nil {
+                       str = fmt.Sprintf("%v(R%d)(NONE)", Mconv(a), a.Reg)
+               }
+
+       case D_CONST:
+               if a.Reg != NREG {
+                       str = fmt.Sprintf("$%v(R%d)", Mconv(a), a.Reg)
+               } else {
+
+                       str = fmt.Sprintf("$%v", Mconv(a))
+               }
+
+       case D_CONST2:
+               str = fmt.Sprintf("$%d-%d", a.Offset, a.Offset2)
+
+       case D_SHIFT:
+               v = int(a.Offset)
+               op = string("<<>>->@>"[((v>>5)&3)<<1:])
+               if v&(1<<4) != 0 {
+                       str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
+               } else {
+
+                       str = fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
+               }
+               if a.Reg != NREG {
+                       str += fmt.Sprintf("(R%d)", a.Reg)
+               }
+
+       case D_OREG:
+               if a.Reg != NREG {
+                       str = fmt.Sprintf("%v(R%d)", Mconv(a), a.Reg)
+               } else {
+
+                       str = fmt.Sprintf("%v", Mconv(a))
+               }
+
+       case D_REG:
+               str = fmt.Sprintf("R%d", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_FREG:
+               str = fmt.Sprintf("F%d", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_PSR:
+               str = fmt.Sprintf("PSR")
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(PSR)(REG)", Mconv(a))
+               }
+
+       case D_BRANCH:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+               } else if p != nil && p.Pcond != nil {
+                       str = fmt.Sprintf("%d", p.Pcond.Pc)
+               } else if a.U.Branch != nil {
+                       str = fmt.Sprintf("%d", a.U.Branch.Pc)
+               } else {
+
+                       str = fmt.Sprintf("%d(PC)", a.Offset) /*-pc*/
+               }
+
+       case D_FCONST:
+               str = fmt.Sprintf("$%.17g", a.U.Dval)
+
+       case D_SCONST:
+               str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+               break
+       }
+
+       fp += str
+       return fp
+}
+
+func RAconv(a *obj.Addr) string {
+       var str string
+       var fp string
+
+       var i int
+       var v int
+
+       str = fmt.Sprintf("GOK-reglist")
+       switch a.Type {
+       case D_CONST,
+               D_CONST2:
+               if a.Reg != NREG {
+                       break
+               }
+               if a.Sym != nil {
+                       break
+               }
+               v = int(a.Offset)
+               str = ""
+               for i = 0; i < NREG; i++ {
+                       if v&(1<<uint(i)) != 0 {
+                               if str[0] == 0 {
+                                       str += "[R"
+                               } else {
+
+                                       str += ",R"
+                               }
+                               str += fmt.Sprintf("%d", i)
+                       }
+               }
+
+               str += "]"
+       }
+
+       fp += str
+       return fp
+}
+
+func Rconv(r int) string {
+       var fp string
+
+       var str string
+
+       str = fmt.Sprintf("R%d", r)
+       fp += str
+       return fp
+}
+
+func DRconv(a int) string {
+       var s string
+       var fp string
+
+       s = "C_??"
+       if a >= C_NONE && a <= C_NCLASS {
+               s = cnames5[a]
+       }
+       fp += s
+       return fp
+}
+
+func Mconv(a *obj.Addr) string {
+       var str string
+       var fp string
+
+       var s *obj.LSym
+
+       s = a.Sym
+       if s == nil {
+               str = fmt.Sprintf("%d", int(a.Offset))
+               goto out
+       }
+
+       switch a.Name {
+       default:
+               str = fmt.Sprintf("GOK-name(%d)", a.Name)
+
+       case D_NONE:
+               str = fmt.Sprintf("%d", a.Offset)
+
+       case D_EXTERN:
+               str = fmt.Sprintf("%s+%d(SB)", s.Name, int(a.Offset))
+
+       case D_STATIC:
+               str = fmt.Sprintf("%s<>+%d(SB)", s.Name, int(a.Offset))
+
+       case D_AUTO:
+               str = fmt.Sprintf("%s-%d(SP)", s.Name, int(-a.Offset))
+
+       case D_PARAM:
+               str = fmt.Sprintf("%s+%d(FP)", s.Name, int(a.Offset))
+               break
+       }
+
+out:
+       fp += str
+       return fp
+}
diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go
new file mode 100644 (file)
index 0000000..d59c9df
--- /dev/null
@@ -0,0 +1,1172 @@
+// Derived from Inferno utils/5c/swt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.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.
+
+package arm
+
+import (
+       "cmd/internal/obj"
+       "encoding/binary"
+       "fmt"
+       "log"
+       "math"
+)
+
+var zprg5 = obj.Prog{
+       As:    AGOK,
+       Scond: C_SCOND_NONE,
+       Reg:   NREG,
+       From: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+       To: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+}
+
+func symtype(a *obj.Addr) int {
+       return int(a.Name)
+}
+
+func isdata(p *obj.Prog) bool {
+       return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+       return p.As == ABL
+}
+
+func datasize(p *obj.Prog) int {
+       return int(p.Reg)
+}
+
+func textflag(p *obj.Prog) int {
+       return int(p.Reg)
+}
+
+func settextflag(p *obj.Prog, f int) {
+       p.Reg = uint8(f)
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+       var literal string
+       var s *obj.LSym
+       var tlsfallback *obj.LSym
+
+       p.From.Class = 0
+       p.To.Class = 0
+
+       // Rewrite B/BL to symbol as D_BRANCH.
+       switch p.As {
+
+       case AB,
+               ABL,
+               ADUFFZERO,
+               ADUFFCOPY:
+               if p.To.Type == D_OREG && (p.To.Name == D_EXTERN || p.To.Name == D_STATIC) && p.To.Sym != nil {
+                       p.To.Type = D_BRANCH
+               }
+               break
+       }
+
+       // Replace TLS register fetches on older ARM procesors.
+       switch p.As {
+
+       // Treat MRC 15, 0, <reg>, C13, C0, 3 specially.
+       case AMRC:
+               if p.To.Offset&0xffff0fff == 0xee1d0f70 {
+
+                       // Because the instruction might be rewriten to a BL which returns in R0
+                       // the register must be zero.
+                       if p.To.Offset&0xf000 != 0 {
+
+                               ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line())
+                       }
+
+                       if ctxt.Goarm < 7 {
+                               // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
+                               if tlsfallback == nil {
+
+                                       tlsfallback = obj.Linklookup(ctxt, "runtime.read_tls_fallback", 0)
+                               }
+
+                               // MOVW LR, R11
+                               p.As = AMOVW
+
+                               p.From.Type = D_REG
+                               p.From.Reg = REGLINK
+                               p.To.Type = D_REG
+                               p.To.Reg = REGTMP
+
+                               // BL   runtime.read_tls_fallback(SB)
+                               p = obj.Appendp(ctxt, p)
+
+                               p.As = ABL
+                               p.To.Type = D_BRANCH
+                               p.To.Sym = tlsfallback
+                               p.To.Offset = 0
+
+                               // MOVW R11, LR
+                               p = obj.Appendp(ctxt, p)
+
+                               p.As = AMOVW
+                               p.From.Type = D_REG
+                               p.From.Reg = REGTMP
+                               p.To.Type = D_REG
+                               p.To.Reg = REGLINK
+                               break
+                       }
+               }
+
+               // Otherwise, MRC/MCR instructions need no further treatment.
+               p.As = AWORD
+
+               break
+       }
+
+       // Rewrite float constants to values stored in memory.
+       switch p.As {
+
+       case AMOVF:
+               if p.From.Type == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
+                       var i32 uint32
+                       var f32 float32
+                       f32 = float32(p.From.U.Dval)
+                       i32 = math.Float32bits(f32)
+                       literal = fmt.Sprintf("$f32.%08x", i32)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint32(ctxt, s, i32)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_OREG
+                       p.From.Sym = s
+                       p.From.Name = D_EXTERN
+                       p.From.Offset = 0
+               }
+
+       case AMOVD:
+               if p.From.Type == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
+                       var i64 uint64
+                       i64 = math.Float64bits(p.From.U.Dval)
+                       literal = fmt.Sprintf("$f64.%016x", i64)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint64(ctxt, s, i64)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_OREG
+                       p.From.Sym = s
+                       p.From.Name = D_EXTERN
+                       p.From.Offset = 0
+               }
+
+               break
+       }
+
+       if ctxt.Flag_shared != 0 {
+               // Shared libraries use R_ARM_TLS_IE32 instead of
+               // R_ARM_TLS_LE32, replacing the link time constant TLS offset in
+               // runtime.tlsg with an address to a GOT entry containing the
+               // offset. Rewrite $runtime.tlsg(SB) to runtime.tlsg(SB) to
+               // compensate.
+               if ctxt.Tlsg == nil {
+
+                       ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+               }
+
+               if p.From.Type == D_CONST && p.From.Name == D_EXTERN && p.From.Sym == ctxt.Tlsg {
+                       p.From.Type = D_OREG
+               }
+               if p.To.Type == D_CONST && p.To.Name == D_EXTERN && p.To.Sym == ctxt.Tlsg {
+                       p.To.Type = D_OREG
+               }
+       }
+}
+
+func prg() *obj.Prog {
+       p := zprg
+       return &p
+}
+
+// Prog.mark
+const (
+       FOLL  = 1 << 0
+       LABEL = 1 << 1
+       LEAF  = 1 << 2
+)
+
+func linkcase(casep *obj.Prog) {
+       var p *obj.Prog
+
+       for p = casep; p != nil; p = p.Link {
+               if p.As == ABCASE {
+                       for ; p != nil && p.As == ABCASE; p = p.Link {
+                               p.Pcrel = casep
+                       }
+                       break
+               }
+       }
+}
+
+func nocache5(p *obj.Prog) {
+       p.Optab = 0
+       p.From.Class = 0
+       p.To.Class = 0
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var pl *obj.Prog
+       var p1 *obj.Prog
+       var p2 *obj.Prog
+       var q *obj.Prog
+       var q1 *obj.Prog
+       var q2 *obj.Prog
+       var o int
+       var autosize int32
+       var autoffset int32
+
+       autosize = 0
+
+       if ctxt.Symmorestack[0] == nil {
+               ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+               ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+       }
+
+       q = nil
+
+       ctxt.Cursym = cursym
+
+       if cursym.Text == nil || cursym.Text.Link == nil {
+               return
+       }
+
+       softfloat(ctxt, cursym)
+
+       p = cursym.Text
+       autoffset = int32(p.To.Offset)
+       if autoffset < 0 {
+               autoffset = 0
+       }
+       cursym.Locals = autoffset
+       cursym.Args = p.To.Offset2
+
+       if ctxt.Debugzerostack != 0 {
+               if autoffset != 0 && !(p.Reg&obj.NOSPLIT != 0) {
+                       // MOVW $4(R13), R1
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.From.Type = D_CONST
+                       p.From.Reg = 13
+                       p.From.Offset = 4
+                       p.To.Type = D_REG
+                       p.To.Reg = 1
+
+                       // MOVW $n(R13), R2
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.From.Type = D_CONST
+                       p.From.Reg = 13
+                       p.From.Offset = 4 + int64(autoffset)
+                       p.To.Type = D_REG
+                       p.To.Reg = 2
+
+                       // MOVW $0, R3
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.From.Type = D_CONST
+                       p.From.Offset = 0
+                       p.To.Type = D_REG
+                       p.To.Reg = 3
+
+                       // L:
+                       //      MOVW.nil R3, 0(R1) +4
+                       //      CMP R1, R2
+                       //      BNE L
+                       pl = obj.Appendp(ctxt, p)
+                       p = pl
+
+                       p.As = AMOVW
+                       p.From.Type = D_REG
+                       p.From.Reg = 3
+                       p.To.Type = D_OREG
+                       p.To.Reg = 1
+                       p.To.Offset = 4
+                       p.Scond |= C_PBIT
+
+                       p = obj.Appendp(ctxt, p)
+                       p.As = ACMP
+                       p.From.Type = D_REG
+                       p.From.Reg = 1
+                       p.Reg = 2
+
+                       p = obj.Appendp(ctxt, p)
+                       p.As = ABNE
+                       p.To.Type = D_BRANCH
+                       p.Pcond = pl
+               }
+       }
+
+       /*
+        * find leaf subroutines
+        * strip NOPs
+        * expand RET
+        * expand BECOME pseudo
+        */
+       for p = cursym.Text; p != nil; p = p.Link {
+
+               switch p.As {
+               case ACASE:
+                       if ctxt.Flag_shared != 0 {
+                               linkcase(p)
+                       }
+
+               case ATEXT:
+                       p.Mark |= LEAF
+
+               case ARET:
+                       break
+
+               case ADIV,
+                       ADIVU,
+                       AMOD,
+                       AMODU:
+                       q = p
+                       if ctxt.Sym_div == nil {
+                               initdiv(ctxt)
+                       }
+                       cursym.Text.Mark &^= LEAF
+                       continue
+
+               case ANOP:
+                       q1 = p.Link
+                       q.Link = q1 /* q is non-nop */
+                       if q1 != nil {
+                               q1.Mark |= p.Mark
+                       }
+                       continue
+
+               case ABL,
+                       ABX,
+                       ADUFFZERO,
+                       ADUFFCOPY:
+                       cursym.Text.Mark &^= LEAF
+                       fallthrough
+
+               case ABCASE,
+                       AB,
+                       ABEQ,
+                       ABNE,
+                       ABCS,
+                       ABHS,
+                       ABCC,
+                       ABLO,
+                       ABMI,
+                       ABPL,
+                       ABVS,
+                       ABVC,
+                       ABHI,
+                       ABLS,
+                       ABGE,
+                       ABLT,
+                       ABGT,
+                       ABLE:
+                       q1 = p.Pcond
+                       if q1 != nil {
+                               for q1.As == ANOP {
+                                       q1 = q1.Link
+                                       p.Pcond = q1
+                               }
+                       }
+
+                       break
+               }
+
+               q = p
+       }
+
+       for p = cursym.Text; p != nil; p = p.Link {
+               o = int(p.As)
+               switch o {
+               case ATEXT:
+                       autosize = int32(p.To.Offset + 4)
+                       if autosize <= 4 {
+                               if cursym.Text.Mark&LEAF != 0 {
+                                       p.To.Offset = -4
+                                       autosize = 0
+                               }
+                       }
+
+                       if !(autosize != 0) && !(cursym.Text.Mark&LEAF != 0) {
+                               if ctxt.Debugvlog != 0 {
+                                       fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+                                       obj.Bflush(ctxt.Bso)
+                               }
+
+                               cursym.Text.Mark |= LEAF
+                       }
+
+                       if cursym.Text.Mark&LEAF != 0 {
+                               cursym.Leaf = 1
+                               if !(autosize != 0) {
+                                       break
+                               }
+                       }
+
+                       if !(p.Reg&obj.NOSPLIT != 0) {
+                               p = stacksplit(ctxt, p, autosize, bool2int(!(cursym.Text.Reg&obj.NEEDCTXT != 0))) // emit split check
+                       }
+
+                       // MOVW.W               R14,$-autosize(SP)
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.Scond |= C_WBIT
+                       p.From.Type = D_REG
+                       p.From.Reg = REGLINK
+                       p.To.Type = D_OREG
+                       p.To.Offset = int64(-autosize)
+                       p.To.Reg = REGSP
+                       p.Spadj = autosize
+
+                       if cursym.Text.Reg&obj.WRAPPER != 0 {
+                               // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+                               //
+                               //      MOVW g_panic(g), R1
+                               //      CMP $0, R1
+                               //      B.EQ end
+                               //      MOVW panic_argp(R1), R2
+                               //      ADD $(autosize+4), R13, R3
+                               //      CMP R2, R3
+                               //      B.NE end
+                               //      ADD $4, R13, R4
+                               //      MOVW R4, panic_argp(R1)
+                               // end:
+                               //      NOP
+                               //
+                               // The NOP is needed to give the jumps somewhere to land.
+                               // It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes.
+
+                               p = obj.Appendp(ctxt, p)
+
+                               p.As = AMOVW
+                               p.From.Type = D_OREG
+                               p.From.Reg = REGG
+                               p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+                               p.To.Type = D_REG
+                               p.To.Reg = 1
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = ACMP
+                               p.From.Type = D_CONST
+                               p.From.Offset = 0
+                               p.Reg = 1
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = ABEQ
+                               p.To.Type = D_BRANCH
+                               p1 = p
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = AMOVW
+                               p.From.Type = D_OREG
+                               p.From.Reg = 1
+                               p.From.Offset = 0 // Panic.argp
+                               p.To.Type = D_REG
+                               p.To.Reg = 2
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = AADD
+                               p.From.Type = D_CONST
+                               p.From.Offset = int64(autosize) + 4
+                               p.Reg = 13
+                               p.To.Type = D_REG
+                               p.To.Reg = 3
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = ACMP
+                               p.From.Type = D_REG
+                               p.From.Reg = 2
+                               p.Reg = 3
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = ABNE
+                               p.To.Type = D_BRANCH
+                               p2 = p
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = AADD
+                               p.From.Type = D_CONST
+                               p.From.Offset = 4
+                               p.Reg = 13
+                               p.To.Type = D_REG
+                               p.To.Reg = 4
+
+                               p = obj.Appendp(ctxt, p)
+                               p.As = AMOVW
+                               p.From.Type = D_REG
+                               p.From.Reg = 4
+                               p.To.Type = D_OREG
+                               p.To.Reg = 1
+                               p.To.Offset = 0 // Panic.argp
+
+                               p = obj.Appendp(ctxt, p)
+
+                               p.As = ANOP
+                               p1.Pcond = p
+                               p2.Pcond = p
+                       }
+
+               case ARET:
+                       nocache5(p)
+                       if cursym.Text.Mark&LEAF != 0 {
+                               if !(autosize != 0) {
+                                       p.As = AB
+                                       p.From = zprg5.From
+                                       if p.To.Sym != nil { // retjmp
+                                               p.To.Type = D_BRANCH
+                                       } else {
+
+                                               p.To.Type = D_OREG
+                                               p.To.Offset = 0
+                                               p.To.Reg = REGLINK
+                                       }
+
+                                       break
+                               }
+                       }
+
+                       p.As = AMOVW
+                       p.Scond |= C_PBIT
+                       p.From.Type = D_OREG
+                       p.From.Offset = int64(autosize)
+                       p.From.Reg = REGSP
+                       p.To.Type = D_REG
+                       p.To.Reg = REGPC
+
+                       // If there are instructions following
+                       // this ARET, they come from a branch
+                       // with the same stackframe, so no spadj.
+                       if p.To.Sym != nil { // retjmp
+                               p.To.Reg = REGLINK
+                               q2 = obj.Appendp(ctxt, p)
+                               q2.As = AB
+                               q2.To.Type = D_BRANCH
+                               q2.To.Sym = p.To.Sym
+                               p.To.Sym = nil
+                               p = q2
+                       }
+
+               case AADD:
+                       if p.From.Type == D_CONST && p.From.Reg == NREG && p.To.Type == D_REG && p.To.Reg == REGSP {
+                               p.Spadj = int32(-p.From.Offset)
+                       }
+
+               case ASUB:
+                       if p.From.Type == D_CONST && p.From.Reg == NREG && p.To.Type == D_REG && p.To.Reg == REGSP {
+                               p.Spadj = int32(p.From.Offset)
+                       }
+
+               case ADIV,
+                       ADIVU,
+                       AMOD,
+                       AMODU:
+                       if ctxt.Debugdivmod != 0 {
+                               break
+                       }
+                       if p.From.Type != D_REG {
+                               break
+                       }
+                       if p.To.Type != D_REG {
+                               break
+                       }
+                       q1 = p
+
+                       /* MOV a,4(SP) */
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.Lineno = q1.Lineno
+                       p.From.Type = D_REG
+                       p.From.Reg = q1.From.Reg
+                       p.To.Type = D_OREG
+                       p.To.Reg = REGSP
+                       p.To.Offset = 4
+
+                       /* MOV b,REGTMP */
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.Lineno = q1.Lineno
+                       p.From.Type = D_REG
+                       p.From.Reg = int8(q1.Reg)
+                       if q1.Reg == NREG {
+                               p.From.Reg = q1.To.Reg
+                       }
+                       p.To.Type = D_REG
+                       p.To.Reg = REGTMP
+                       p.To.Offset = 0
+
+                       /* CALL appropriate */
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = ABL
+                       p.Lineno = q1.Lineno
+                       p.To.Type = D_BRANCH
+                       switch o {
+                       case ADIV:
+                               p.To.Sym = ctxt.Sym_div
+
+                       case ADIVU:
+                               p.To.Sym = ctxt.Sym_divu
+
+                       case AMOD:
+                               p.To.Sym = ctxt.Sym_mod
+
+                       case AMODU:
+                               p.To.Sym = ctxt.Sym_modu
+                               break
+                       }
+
+                       /* MOV REGTMP, b */
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AMOVW
+                       p.Lineno = q1.Lineno
+                       p.From.Type = D_REG
+                       p.From.Reg = REGTMP
+                       p.From.Offset = 0
+                       p.To.Type = D_REG
+                       p.To.Reg = q1.To.Reg
+
+                       /* ADD $8,SP */
+                       p = obj.Appendp(ctxt, p)
+
+                       p.As = AADD
+                       p.Lineno = q1.Lineno
+                       p.From.Type = D_CONST
+                       p.From.Reg = NREG
+                       p.From.Offset = 8
+                       p.Reg = NREG
+                       p.To.Type = D_REG
+                       p.To.Reg = REGSP
+                       p.Spadj = -8
+
+                       /* Keep saved LR at 0(SP) after SP change. */
+                       /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
+                       /* TODO: Remove SP adjustments; see issue 6699. */
+                       q1.As = AMOVW
+
+                       q1.From.Type = D_OREG
+                       q1.From.Reg = REGSP
+                       q1.From.Offset = 0
+                       q1.Reg = NREG
+                       q1.To.Type = D_REG
+                       q1.To.Reg = REGTMP
+
+                       /* SUB $8,SP */
+                       q1 = obj.Appendp(ctxt, q1)
+
+                       q1.As = AMOVW
+                       q1.From.Type = D_REG
+                       q1.From.Reg = REGTMP
+                       q1.Reg = NREG
+                       q1.To.Type = D_OREG
+                       q1.To.Reg = REGSP
+                       q1.To.Offset = -8
+                       q1.Scond |= C_WBIT
+                       q1.Spadj = 8
+
+               case AMOVW:
+                       if (p.Scond&C_WBIT != 0) && p.To.Type == D_OREG && p.To.Reg == REGSP {
+                               p.Spadj = int32(-p.To.Offset)
+                       }
+                       if (p.Scond&C_PBIT != 0) && p.From.Type == D_OREG && p.From.Reg == REGSP && p.To.Reg != REGPC {
+                               p.Spadj = int32(-p.From.Offset)
+                       }
+                       if p.From.Type == D_CONST && p.From.Reg == REGSP && p.To.Type == D_REG && p.To.Reg == REGSP {
+                               p.Spadj = int32(-p.From.Offset)
+                       }
+                       break
+               }
+       }
+}
+
+func softfloat(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var next *obj.Prog
+       var symsfloat *obj.LSym
+       var wasfloat int
+
+       if ctxt.Goarm > 5 {
+               return
+       }
+
+       symsfloat = obj.Linklookup(ctxt, "_sfloat", 0)
+
+       wasfloat = 0
+       for p = cursym.Text; p != nil; p = p.Link {
+               if p.Pcond != nil {
+                       p.Pcond.Mark |= LABEL
+               }
+       }
+       for p = cursym.Text; p != nil; p = p.Link {
+               switch p.As {
+               case AMOVW:
+                       if p.To.Type == D_FREG || p.From.Type == D_FREG {
+                               goto soft
+                       }
+                       goto notsoft
+
+               case AMOVWD,
+                       AMOVWF,
+                       AMOVDW,
+                       AMOVFW,
+                       AMOVFD,
+                       AMOVDF,
+                       AMOVF,
+                       AMOVD,
+                       ACMPF,
+                       ACMPD,
+                       AADDF,
+                       AADDD,
+                       ASUBF,
+                       ASUBD,
+                       AMULF,
+                       AMULD,
+                       ADIVF,
+                       ADIVD,
+                       ASQRTF,
+                       ASQRTD,
+                       AABSF,
+                       AABSD:
+                       goto soft
+
+               default:
+                       goto notsoft
+               }
+
+       soft:
+               if !(wasfloat != 0) || (p.Mark&LABEL != 0) {
+                       next = ctxt.NewProg()
+                       *next = *p
+
+                       // BL _sfloat(SB)
+                       *p = zprg5
+
+                       p.Link = next
+                       p.As = ABL
+                       p.To.Type = D_BRANCH
+                       p.To.Sym = symsfloat
+                       p.Lineno = next.Lineno
+
+                       p = next
+                       wasfloat = 1
+               }
+
+               continue
+
+       notsoft:
+               wasfloat = 0
+       }
+}
+
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int) *obj.Prog {
+       // MOVW                 g_stackguard(g), R1
+       p = obj.Appendp(ctxt, p)
+
+       p.As = AMOVW
+       p.From.Type = D_OREG
+       p.From.Reg = REGG
+       p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+       if ctxt.Cursym.Cfunc != 0 {
+               p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+       }
+       p.To.Type = D_REG
+       p.To.Reg = 1
+
+       if framesize <= obj.StackSmall {
+               // small stack: SP < stackguard
+               //      CMP     stackguard, SP
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ACMP
+               p.From.Type = D_REG
+               p.From.Reg = 1
+               p.Reg = REGSP
+       } else if framesize <= obj.StackBig {
+               // large stack: SP-framesize < stackguard-StackSmall
+               //      MOVW $-framesize(SP), R2
+               //      CMP stackguard, R2
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVW
+               p.From.Type = D_CONST
+               p.From.Reg = REGSP
+               p.From.Offset = int64(-framesize)
+               p.To.Type = D_REG
+               p.To.Reg = 2
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMP
+               p.From.Type = D_REG
+               p.From.Reg = 1
+               p.Reg = 2
+       } 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.
+               //      CMP $StackPreempt, R1
+               //      MOVW.NE $StackGuard(SP), R2
+               //      SUB.NE R1, R2
+               //      MOVW.NE $(framesize+(StackGuard-StackSmall)), R3
+               //      CMP.NE R3, R2
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ACMP
+               p.From.Type = D_CONST
+               p.From.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1)))
+               p.Reg = 1
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVW
+               p.From.Type = D_CONST
+               p.From.Reg = REGSP
+               p.From.Offset = obj.StackGuard
+               p.To.Type = D_REG
+               p.To.Reg = 2
+               p.Scond = C_SCOND_NE
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ASUB
+               p.From.Type = D_REG
+               p.From.Reg = 1
+               p.To.Type = D_REG
+               p.To.Reg = 2
+               p.Scond = C_SCOND_NE
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVW
+               p.From.Type = D_CONST
+               p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+               p.To.Type = D_REG
+               p.To.Reg = 3
+               p.Scond = C_SCOND_NE
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMP
+               p.From.Type = D_REG
+               p.From.Reg = 3
+               p.Reg = 2
+               p.Scond = C_SCOND_NE
+       }
+
+       // MOVW.LS      R14, R3
+       p = obj.Appendp(ctxt, p)
+
+       p.As = AMOVW
+       p.Scond = C_SCOND_LS
+       p.From.Type = D_REG
+       p.From.Reg = REGLINK
+       p.To.Type = D_REG
+       p.To.Reg = 3
+
+       // BL.LS                runtime.morestack(SB) // modifies LR, returns with LO still asserted
+       p = obj.Appendp(ctxt, p)
+
+       p.As = ABL
+       p.Scond = C_SCOND_LS
+       p.To.Type = D_BRANCH
+       if ctxt.Cursym.Cfunc != 0 {
+               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+       } else {
+
+               p.To.Sym = ctxt.Symmorestack[noctxt]
+       }
+
+       // BLS  start
+       p = obj.Appendp(ctxt, p)
+
+       p.As = ABLS
+       p.To.Type = D_BRANCH
+       p.Pcond = ctxt.Cursym.Text.Link
+
+       return p
+}
+
+func initdiv(ctxt *obj.Link) {
+       if ctxt.Sym_div != nil {
+               return
+       }
+       ctxt.Sym_div = obj.Linklookup(ctxt, "_div", 0)
+       ctxt.Sym_divu = obj.Linklookup(ctxt, "_divu", 0)
+       ctxt.Sym_mod = obj.Linklookup(ctxt, "_mod", 0)
+       ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0)
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+       var firstp *obj.Prog
+       var lastp *obj.Prog
+
+       ctxt.Cursym = s
+
+       firstp = ctxt.NewProg()
+       lastp = firstp
+       xfol(ctxt, s.Text, &lastp)
+       lastp.Link = nil
+       s.Text = firstp.Link
+}
+
+func relinv(a int) int {
+       switch a {
+       case ABEQ:
+               return ABNE
+       case ABNE:
+               return ABEQ
+       case ABCS:
+               return ABCC
+       case ABHS:
+               return ABLO
+       case ABCC:
+               return ABCS
+       case ABLO:
+               return ABHS
+       case ABMI:
+               return ABPL
+       case ABPL:
+               return ABMI
+       case ABVS:
+               return ABVC
+       case ABVC:
+               return ABVS
+       case ABHI:
+               return ABLS
+       case ABLS:
+               return ABHI
+       case ABGE:
+               return ABLT
+       case ABLT:
+               return ABGE
+       case ABGT:
+               return ABLE
+       case ABLE:
+               return ABGT
+       }
+
+       log.Fatalf("unknown relation: %s", Anames[a])
+       return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+       var q *obj.Prog
+       var r *obj.Prog
+       var a int
+       var i int
+
+loop:
+       if p == nil {
+               return
+       }
+       a = int(p.As)
+       if a == AB {
+               q = p.Pcond
+               if q != nil && q.As != ATEXT {
+                       p.Mark |= FOLL
+                       p = q
+                       if !(p.Mark&FOLL != 0) {
+                               goto loop
+                       }
+               }
+       }
+
+       if p.Mark&FOLL != 0 {
+               i = 0
+               q = p
+               for ; i < 4; (func() { i++; q = q.Link })() {
+                       if q == *last || q == nil {
+                               break
+                       }
+                       a = int(q.As)
+                       if a == ANOP {
+                               i--
+                               continue
+                       }
+
+                       if a == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+                               goto copy
+                       }
+                       if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
+                               continue
+                       }
+                       if a != ABEQ && a != ABNE {
+                               continue
+                       }
+
+               copy:
+                       for {
+                               r = ctxt.NewProg()
+                               *r = *p
+                               if !(r.Mark&FOLL != 0) {
+                                       fmt.Printf("can't 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 == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+                                       return
+                               }
+                               r.As = ABNE
+                               if a == ABNE {
+                                       r.As = ABEQ
+                               }
+                               r.Pcond = p.Link
+                               r.Link = p.Pcond
+                               if !(r.Link.Mark&FOLL != 0) {
+                                       xfol(ctxt, r.Link, last)
+                               }
+                               if !(r.Pcond.Mark&FOLL != 0) {
+                                       fmt.Printf("can't happen 2\n")
+                               }
+                               return
+                       }
+               }
+
+               a = AB
+               q = ctxt.NewProg()
+               q.As = int16(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 == AB || (a == ARET && p.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+               return
+       }
+
+       if p.Pcond != nil {
+               if a != ABL && a != ABX && p.Link != nil {
+                       q = obj.Brchain(ctxt, p.Link)
+                       if a != ATEXT && a != ABCASE {
+                               if q != nil && (q.Mark&FOLL != 0) {
+                                       p.As = int16(relinv(a))
+                                       p.Link = p.Pcond
+                                       p.Pcond = q
+                               }
+                       }
+
+                       xfol(ctxt, p.Link, last)
+                       q = obj.Brchain(ctxt, p.Pcond)
+                       if q == nil {
+                               q = p.Pcond
+                       }
+                       if q.Mark&FOLL != 0 {
+                               p.Pcond = q
+                               return
+                       }
+
+                       p = q
+                       goto loop
+               }
+       }
+
+       p = p.Link
+       goto loop
+}
+
+var Linkarm = obj.LinkArch{
+       ByteOrder:     binary.LittleEndian,
+       Pconv:         Pconv,
+       Name:          "arm",
+       Thechar:       '5',
+       Endian:        obj.LittleEndian,
+       Addstacksplit: addstacksplit,
+       Assemble:      span5,
+       Datasize:      datasize,
+       Follow:        follow,
+       Iscall:        iscall,
+       Isdata:        isdata,
+       Prg:           prg,
+       Progedit:      progedit,
+       Settextflag:   settextflag,
+       Symtype:       symtype,
+       Textflag:      textflag,
+       Minlc:         4,
+       Ptrsize:       4,
+       Regsize:       4,
+       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,
+       D_OREG:        D_OREG,
+       ACALL:         ABL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          AB,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARET,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
diff --git a/src/cmd/internal/obj/arm/util.go b/src/cmd/internal/obj/arm/util.go
new file mode 100644 (file)
index 0000000..f036c5f
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package arm
+
+func bool2int(b bool) int {
+       if b {
+               return 1
+       }
+       return 0
+}
diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go
new file mode 100644 (file)
index 0000000..35d5182
--- /dev/null
@@ -0,0 +1,292 @@
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.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.
+
+package obj
+
+import (
+       "log"
+       "math"
+)
+
+func mangle(file string) {
+
+       log.Fatalf("%s: mangled input file", file)
+}
+
+func Symgrow(ctxt *Link, s *LSym, lsiz int64) {
+       var siz int
+       siz = int(lsiz)
+       if int64(siz) != lsiz {
+               log.Fatal("Symgrow size %d too long", lsiz)
+       }
+       if len(s.P) >= siz {
+               return
+       }
+       for cap(s.P) < siz {
+               s.P = append(s.P[:cap(s.P)], 0)
+       }
+       s.P = s.P[:siz]
+}
+
+func savedata(ctxt *Link, s *LSym, p *Prog, pn string) {
+       off := int32(p.From.Offset)
+       siz := int32(ctxt.Arch.Datasize(p))
+       if off < 0 || siz < 0 || off >= 1<<30 || siz >= 100 {
+               mangle(pn)
+       }
+       if ctxt.Enforce_data_order != 0 && off < int32(len(s.P)) {
+               ctxt.Diag("data out of order (already have %d)\n%P", len(s.P), p)
+       }
+       Symgrow(ctxt, s, int64(off+siz))
+
+       switch int(p.To.Type) {
+       default:
+               ctxt.Diag("bad data: %P", p)
+
+       case ctxt.Arch.D_FCONST:
+               switch siz {
+               default:
+                       ctxt.Diag("unexpected %d-byte floating point constant", siz)
+
+               case 4:
+                       flt := math.Float32bits(float32(p.To.U.Dval))
+                       ctxt.Arch.ByteOrder.PutUint32(s.P[off:], flt)
+
+               case 8:
+                       flt := math.Float64bits(p.To.U.Dval)
+                       ctxt.Arch.ByteOrder.PutUint64(s.P[off:], flt)
+               }
+
+       case ctxt.Arch.D_SCONST:
+               copy(s.P[off:off+siz], p.To.U.Sval)
+
+       case ctxt.Arch.D_CONST, ctxt.Arch.D_ADDR:
+               if p.To.Sym != nil || int(p.To.Type) == ctxt.Arch.D_ADDR {
+                       r := Addrel(s)
+                       r.Off = off
+                       r.Siz = uint8(siz)
+                       r.Sym = p.To.Sym
+                       r.Type = R_ADDR
+                       r.Add = p.To.Offset
+                       break
+               }
+               o := p.To.Offset
+               switch siz {
+               default:
+                       ctxt.Diag("unexpected %d-byte integer constant", siz)
+               case 1:
+                       s.P[off] = byte(o)
+               case 2:
+                       ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(o))
+               case 4:
+                       ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(o))
+               case 8:
+                       ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
+               }
+       }
+}
+
+func Addrel(s *LSym) *Reloc {
+       s.R = append(s.R, Reloc{})
+       return &s.R[len(s.R)-1]
+}
+
+func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       if s.Size < off+wid {
+               s.Size = off + wid
+               Symgrow(ctxt, s, s.Size)
+       }
+
+       switch wid {
+       case 1:
+               s.P[off] = uint8(v)
+       case 2:
+               ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
+       case 4:
+               ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
+       case 8:
+               ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v))
+       }
+
+       return off + wid
+}
+
+func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
+       var off int64
+
+       off = s.Size
+       setuintxx(ctxt, s, off, v, int64(wid))
+       return off
+}
+
+func adduint8(ctxt *Link, s *LSym, v uint8) int64 {
+       return adduintxx(ctxt, s, uint64(v), 1)
+}
+
+func adduint16(ctxt *Link, s *LSym, v uint16) int64 {
+       return adduintxx(ctxt, s, uint64(v), 2)
+}
+
+func Adduint32(ctxt *Link, s *LSym, v uint32) int64 {
+       return adduintxx(ctxt, s, uint64(v), 4)
+}
+
+func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
+       return adduintxx(ctxt, s, v, 8)
+}
+
+func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
+       return setuintxx(ctxt, s, r, uint64(v), 1)
+}
+
+func setuint16(ctxt *Link, s *LSym, r int64, v uint16) int64 {
+       return setuintxx(ctxt, s, r, uint64(v), 2)
+}
+
+func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 {
+       return setuintxx(ctxt, s, r, uint64(v), 4)
+}
+
+func setuint64(ctxt *Link, s *LSym, r int64, v uint64) int64 {
+       return setuintxx(ctxt, s, r, v, 8)
+}
+
+func addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+       var i int64
+       var r *Reloc
+
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       i = s.Size
+       s.Size += int64(ctxt.Arch.Ptrsize)
+       Symgrow(ctxt, s, s.Size)
+       r = Addrel(s)
+       r.Sym = t
+       r.Off = int32(i)
+       r.Siz = uint8(ctxt.Arch.Ptrsize)
+       r.Type = R_ADDR
+       r.Add = add
+       return i + int64(r.Siz)
+}
+
+func addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+       var i int64
+       var r *Reloc
+
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       i = s.Size
+       s.Size += 4
+       Symgrow(ctxt, s, s.Size)
+       r = Addrel(s)
+       r.Sym = t
+       r.Off = int32(i)
+       r.Add = add
+       r.Type = R_PCREL
+       r.Siz = 4
+       return i + int64(r.Siz)
+}
+
+func addaddr(ctxt *Link, s *LSym, t *LSym) int64 {
+       return addaddrplus(ctxt, s, t, 0)
+}
+
+func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
+       var r *Reloc
+
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       if off+int64(ctxt.Arch.Ptrsize) > s.Size {
+               s.Size = off + int64(ctxt.Arch.Ptrsize)
+               Symgrow(ctxt, s, s.Size)
+       }
+
+       r = Addrel(s)
+       r.Sym = t
+       r.Off = int32(off)
+       r.Siz = uint8(ctxt.Arch.Ptrsize)
+       r.Type = R_ADDR
+       r.Add = add
+       return off + int64(r.Siz)
+}
+
+func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 {
+       return setaddrplus(ctxt, s, off, t, 0)
+}
+
+func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
+       var i int64
+       var r *Reloc
+
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       i = s.Size
+       s.Size += int64(ctxt.Arch.Ptrsize)
+       Symgrow(ctxt, s, s.Size)
+       r = Addrel(s)
+       r.Sym = t
+       r.Off = int32(i)
+       r.Siz = uint8(ctxt.Arch.Ptrsize)
+       r.Type = R_SIZE
+       return i + int64(r.Siz)
+}
+
+func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+       var i int64
+       var r *Reloc
+
+       if s.Type == 0 {
+               s.Type = SDATA
+       }
+       s.Reachable = 1
+       i = s.Size
+       s.Size += 4
+       Symgrow(ctxt, s, s.Size)
+       r = Addrel(s)
+       r.Sym = t
+       r.Off = int32(i)
+       r.Siz = 4
+       r.Type = R_ADDR
+       r.Add = add
+       return i + int64(r.Siz)
+}
diff --git a/src/cmd/internal/obj/fmt.go b/src/cmd/internal/obj/fmt.go
new file mode 100644 (file)
index 0000000..6bb5c42
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ *              Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+package obj
+
+// (The comments in this file were copied from the manpage files rune.3,
+// isalpharune.3, and runestrcat.3. Some formatting changes were also made
+// to conform to Google style. /JRM 11/11/05)
+
+type Fmt struct {
+       runes     uint8
+       start     interface{}
+       to        interface{}
+       stop      interface{}
+       flush     func(*Fmt) int
+       farg      interface{}
+       nfmt      int
+       args      []interface{}
+       r         uint
+       width     int
+       prec      int
+       flags     uint32
+       decimal   string
+       thousands string
+       grouping  string
+}
+
+const (
+       FmtWidth    = 1
+       FmtLeft     = FmtWidth << 1
+       FmtPrec     = FmtLeft << 1
+       FmtSharp    = FmtPrec << 1
+       FmtSpace    = FmtSharp << 1
+       FmtSign     = FmtSpace << 1
+       FmtApost    = FmtSign << 1
+       FmtZero     = FmtApost << 1
+       FmtUnsigned = FmtZero << 1
+       FmtShort    = FmtUnsigned << 1
+       FmtLong     = FmtShort << 1
+       FmtVLong    = FmtLong << 1
+       FmtComma    = FmtVLong << 1
+       FmtByte     = FmtComma << 1
+       FmtLDouble  = FmtByte << 1
+       FmtFlag     = FmtLDouble << 1
+)
+
+var fmtdoquote func(int) int
+
+/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/fmt/?*.c | grep -v static |grep -v __ */
diff --git a/src/cmd/internal/obj/funcdata.go b/src/cmd/internal/obj/funcdata.go
new file mode 100644 (file)
index 0000000..1d10b22
--- /dev/null
@@ -0,0 +1,78 @@
+// 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.
+
+package obj
+
+// Copyright 2013 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.
+
+// This file defines the IDs for PCDATA and FUNCDATA instructions
+// in Go binaries. It is included by assembly sources, so it must
+// be written using #defines.
+//
+// The Go compiler also #includes this file, for now.
+//
+// symtab.go also contains a copy of these constants.
+
+// Pseudo-assembly statements.
+
+// GO_ARGS, GO_RESULTS_INITIALIZED, and NO_LOCAL_POINTERS are macros
+// that communicate to the runtime information about the location and liveness
+// of pointers in an assembly function's arguments, results, and stack frame.
+// This communication is only required in assembly functions that make calls
+// to other functions that might be preempted or grow the stack.
+// NOSPLIT functions that make no calls do not need to use these macros.
+
+// GO_ARGS indicates that the Go prototype for this assembly function
+// defines the pointer map for the function's arguments.
+// GO_ARGS should be the first instruction in a function that uses it.
+// It can be omitted if there are no arguments at all.
+// GO_ARGS is inserted implicitly by the linker for any function
+// that also has a Go prototype and therefore is usually not necessary
+// to write explicitly.
+
+// GO_RESULTS_INITIALIZED indicates that the assembly function
+// has initialized the stack space for its results and that those results
+// should be considered live for the remainder of the function.
+
+// NO_LOCAL_POINTERS indicates that the assembly function stores
+// no pointers to heap objects in its local stack variables.
+
+// ArgsSizeUnknown is set in Func.argsize to mark all functions
+// whose argument size is unknown (C vararg functions, and
+// assembly code without an explicit specification).
+// This value is generated by the compiler, assembler, or linker.
+const (
+       PCDATA_StackMapIndex       = 0
+       FUNCDATA_ArgsPointerMaps   = 0
+       FUNCDATA_LocalsPointerMaps = 1
+       FUNCDATA_DeadValueMaps     = 2
+       ArgsSizeUnknown            = 0x80000000
+)
diff --git a/src/cmd/internal/obj/go.go b/src/cmd/internal/obj/go.go
new file mode 100644 (file)
index 0000000..b0b2183
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+       "math"
+       "strings"
+)
+
+// go-specific code shared across loaders (5l, 6l, 8l).
+
+// replace all "". with pkg.
+func expandpkg(t0 string, pkg string) string {
+       return strings.Replace(t0, `"".`, pkg+".", -1)
+}
+
+func double2ieee(ieee *uint64, f float64) {
+       *ieee = math.Float64bits(f)
+}
diff --git a/src/cmd/internal/obj/i386/8.out.go b/src/cmd/internal/obj/i386/8.out.go
new file mode 100644 (file)
index 0000000..f0e3b33
--- /dev/null
@@ -0,0 +1,627 @@
+// Inferno utils/8c/8.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/8c/8.out.h
+//
+//     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.
+
+package i386
+
+const (
+       AXXX = iota
+       AAAA
+       AAAD
+       AAAM
+       AAAS
+       AADCB
+       AADCL
+       AADCW
+       AADDB
+       AADDL
+       AADDW
+       AADJSP
+       AANDB
+       AANDL
+       AANDW
+       AARPL
+       ABOUNDL
+       ABOUNDW
+       ABSFL
+       ABSFW
+       ABSRL
+       ABSRW
+       ABTL
+       ABTW
+       ABTCL
+       ABTCW
+       ABTRL
+       ABTRW
+       ABTSL
+       ABTSW
+       ABYTE
+       ACALL
+       ACLC
+       ACLD
+       ACLI
+       ACLTS
+       ACMC
+       ACMPB
+       ACMPL
+       ACMPW
+       ACMPSB
+       ACMPSL
+       ACMPSW
+       ADAA
+       ADAS
+       ADATA
+       ADECB
+       ADECL
+       ADECW
+       ADIVB
+       ADIVL
+       ADIVW
+       AENTER
+       AGLOBL
+       AGOK
+       AHISTORY
+       AHLT
+       AIDIVB
+       AIDIVL
+       AIDIVW
+       AIMULB
+       AIMULL
+       AIMULW
+       AINB
+       AINL
+       AINW
+       AINCB
+       AINCL
+       AINCW
+       AINSB
+       AINSL
+       AINSW
+       AINT
+       AINTO
+       AIRETL
+       AIRETW
+       AJCC
+       AJCS
+       AJCXZL
+       AJCXZW
+       AJEQ
+       AJGE
+       AJGT
+       AJHI
+       AJLE
+       AJLS
+       AJLT
+       AJMI
+       AJMP
+       AJNE
+       AJOC
+       AJOS
+       AJPC
+       AJPL
+       AJPS
+       ALAHF
+       ALARL
+       ALARW
+       ALEAL
+       ALEAW
+       ALEAVEL
+       ALEAVEW
+       ALOCK
+       ALODSB
+       ALODSL
+       ALODSW
+       ALONG
+       ALOOP
+       ALOOPEQ
+       ALOOPNE
+       ALSLL
+       ALSLW
+       AMOVB
+       AMOVL
+       AMOVW
+       AMOVQ
+       AMOVBLSX
+       AMOVBLZX
+       AMOVBWSX
+       AMOVBWZX
+       AMOVWLSX
+       AMOVWLZX
+       AMOVSB
+       AMOVSL
+       AMOVSW
+       AMULB
+       AMULL
+       AMULW
+       ANAME
+       ANEGB
+       ANEGL
+       ANEGW
+       ANOP
+       ANOTB
+       ANOTL
+       ANOTW
+       AORB
+       AORL
+       AORW
+       AOUTB
+       AOUTL
+       AOUTW
+       AOUTSB
+       AOUTSL
+       AOUTSW
+       APAUSE
+       APOPAL
+       APOPAW
+       APOPFL
+       APOPFW
+       APOPL
+       APOPW
+       APUSHAL
+       APUSHAW
+       APUSHFL
+       APUSHFW
+       APUSHL
+       APUSHW
+       ARCLB
+       ARCLL
+       ARCLW
+       ARCRB
+       ARCRL
+       ARCRW
+       AREP
+       AREPN
+       ARET
+       AROLB
+       AROLL
+       AROLW
+       ARORB
+       ARORL
+       ARORW
+       ASAHF
+       ASALB
+       ASALL
+       ASALW
+       ASARB
+       ASARL
+       ASARW
+       ASBBB
+       ASBBL
+       ASBBW
+       ASCASB
+       ASCASL
+       ASCASW
+       ASETCC
+       ASETCS
+       ASETEQ
+       ASETGE
+       ASETGT
+       ASETHI
+       ASETLE
+       ASETLS
+       ASETLT
+       ASETMI
+       ASETNE
+       ASETOC
+       ASETOS
+       ASETPC
+       ASETPL
+       ASETPS
+       ACDQ
+       ACWD
+       ASHLB
+       ASHLL
+       ASHLW
+       ASHRB
+       ASHRL
+       ASHRW
+       ASTC
+       ASTD
+       ASTI
+       ASTOSB
+       ASTOSL
+       ASTOSW
+       ASUBB
+       ASUBL
+       ASUBW
+       ASYSCALL
+       ATESTB
+       ATESTL
+       ATESTW
+       ATEXT
+       AVERR
+       AVERW
+       AWAIT
+       AWORD
+       AXCHGB
+       AXCHGL
+       AXCHGW
+       AXLAT
+       AXORB
+       AXORL
+       AXORW
+       AFMOVB
+       AFMOVBP
+       AFMOVD
+       AFMOVDP
+       AFMOVF
+       AFMOVFP
+       AFMOVL
+       AFMOVLP
+       AFMOVV
+       AFMOVVP
+       AFMOVW
+       AFMOVWP
+       AFMOVX
+       AFMOVXP
+       AFCOMB
+       AFCOMBP
+       AFCOMD
+       AFCOMDP
+       AFCOMDPP
+       AFCOMF
+       AFCOMFP
+       AFCOMI
+       AFCOMIP
+       AFCOML
+       AFCOMLP
+       AFCOMW
+       AFCOMWP
+       AFUCOM
+       AFUCOMI
+       AFUCOMIP
+       AFUCOMP
+       AFUCOMPP
+       AFADDDP
+       AFADDW
+       AFADDL
+       AFADDF
+       AFADDD
+       AFMULDP
+       AFMULW
+       AFMULL
+       AFMULF
+       AFMULD
+       AFSUBDP
+       AFSUBW
+       AFSUBL
+       AFSUBF
+       AFSUBD
+       AFSUBRDP
+       AFSUBRW
+       AFSUBRL
+       AFSUBRF
+       AFSUBRD
+       AFDIVDP
+       AFDIVW
+       AFDIVL
+       AFDIVF
+       AFDIVD
+       AFDIVRDP
+       AFDIVRW
+       AFDIVRL
+       AFDIVRF
+       AFDIVRD
+       AFXCHD
+       AFFREE
+       AFLDCW
+       AFLDENV
+       AFRSTOR
+       AFSAVE
+       AFSTCW
+       AFSTENV
+       AFSTSW
+       AF2XM1
+       AFABS
+       AFCHS
+       AFCLEX
+       AFCOS
+       AFDECSTP
+       AFINCSTP
+       AFINIT
+       AFLD1
+       AFLDL2E
+       AFLDL2T
+       AFLDLG2
+       AFLDLN2
+       AFLDPI
+       AFLDZ
+       AFNOP
+       AFPATAN
+       AFPREM
+       AFPREM1
+       AFPTAN
+       AFRNDINT
+       AFSCALE
+       AFSIN
+       AFSINCOS
+       AFSQRT
+       AFTST
+       AFXAM
+       AFXTRACT
+       AFYL2X
+       AFYL2XP1
+       AEND
+       ADYNT_
+       AINIT_
+       ASIGNAME
+       ACMPXCHGB
+       ACMPXCHGL
+       ACMPXCHGW
+       ACMPXCHG8B
+       ACPUID
+       ARDTSC
+       AXADDB
+       AXADDL
+       AXADDW
+       ACMOVLCC
+       ACMOVLCS
+       ACMOVLEQ
+       ACMOVLGE
+       ACMOVLGT
+       ACMOVLHI
+       ACMOVLLE
+       ACMOVLLS
+       ACMOVLLT
+       ACMOVLMI
+       ACMOVLNE
+       ACMOVLOC
+       ACMOVLOS
+       ACMOVLPC
+       ACMOVLPL
+       ACMOVLPS
+       ACMOVWCC
+       ACMOVWCS
+       ACMOVWEQ
+       ACMOVWGE
+       ACMOVWGT
+       ACMOVWHI
+       ACMOVWLE
+       ACMOVWLS
+       ACMOVWLT
+       ACMOVWMI
+       ACMOVWNE
+       ACMOVWOC
+       ACMOVWOS
+       ACMOVWPC
+       ACMOVWPL
+       ACMOVWPS
+       AFCMOVCC
+       AFCMOVCS
+       AFCMOVEQ
+       AFCMOVHI
+       AFCMOVLS
+       AFCMOVNE
+       AFCMOVNU
+       AFCMOVUN
+       ALFENCE
+       AMFENCE
+       ASFENCE
+       AEMMS
+       APREFETCHT0
+       APREFETCHT1
+       APREFETCHT2
+       APREFETCHNTA
+       ABSWAPL
+       AUNDEF
+       AADDPD
+       AADDPS
+       AADDSD
+       AADDSS
+       AANDNPD
+       AANDNPS
+       AANDPD
+       AANDPS
+       ACMPPD
+       ACMPPS
+       ACMPSD
+       ACMPSS
+       ACOMISD
+       ACOMISS
+       ACVTPL2PD
+       ACVTPL2PS
+       ACVTPD2PL
+       ACVTPD2PS
+       ACVTPS2PL
+       ACVTPS2PD
+       ACVTSD2SL
+       ACVTSD2SS
+       ACVTSL2SD
+       ACVTSL2SS
+       ACVTSS2SD
+       ACVTSS2SL
+       ACVTTPD2PL
+       ACVTTPS2PL
+       ACVTTSD2SL
+       ACVTTSS2SL
+       ADIVPD
+       ADIVPS
+       ADIVSD
+       ADIVSS
+       AMASKMOVOU
+       AMAXPD
+       AMAXPS
+       AMAXSD
+       AMAXSS
+       AMINPD
+       AMINPS
+       AMINSD
+       AMINSS
+       AMOVAPD
+       AMOVAPS
+       AMOVO
+       AMOVOU
+       AMOVHLPS
+       AMOVHPD
+       AMOVHPS
+       AMOVLHPS
+       AMOVLPD
+       AMOVLPS
+       AMOVMSKPD
+       AMOVMSKPS
+       AMOVNTO
+       AMOVNTPD
+       AMOVNTPS
+       AMOVSD
+       AMOVSS
+       AMOVUPD
+       AMOVUPS
+       AMULPD
+       AMULPS
+       AMULSD
+       AMULSS
+       AORPD
+       AORPS
+       APADDQ
+       APAND
+       APCMPEQB
+       APMAXSW
+       APMAXUB
+       APMINSW
+       APMINUB
+       APMOVMSKB
+       APSADBW
+       APSUBB
+       APSUBL
+       APSUBQ
+       APSUBSB
+       APSUBSW
+       APSUBUSB
+       APSUBUSW
+       APSUBW
+       APUNPCKHQDQ
+       APUNPCKLQDQ
+       APXOR
+       ARCPPS
+       ARCPSS
+       ARSQRTPS
+       ARSQRTSS
+       ASQRTPD
+       ASQRTPS
+       ASQRTSD
+       ASQRTSS
+       ASUBPD
+       ASUBPS
+       ASUBSD
+       ASUBSS
+       AUCOMISD
+       AUCOMISS
+       AUNPCKHPD
+       AUNPCKHPS
+       AUNPCKLPD
+       AUNPCKLPS
+       AXORPD
+       AXORPS
+       APSHUFHW
+       APSHUFL
+       APSHUFLW
+       AAESENC
+       APINSRD
+       APSHUFB
+       AUSEFIELD
+       ATYPE
+       AFUNCDATA
+       APCDATA
+       ACHECKNIL
+       AVARDEF
+       AVARKILL
+       ADUFFCOPY
+       ADUFFZERO
+       ALAST
+)
+
+const (
+       D_AL = 0 + iota
+       D_CL
+       D_DL
+       D_BL
+       D_AH = 4 + iota - 4
+       D_CH
+       D_DH
+       D_BH
+       D_AX = 8 + iota - 8
+       D_CX
+       D_DX
+       D_BX
+       D_SP
+       D_BP
+       D_SI
+       D_DI
+       D_F0 = 16
+       D_F7 = D_F0 + 7
+       D_CS = 24 + iota - 18
+       D_SS
+       D_DS
+       D_ES
+       D_FS
+       D_GS
+       D_GDTR
+       D_IDTR
+       D_LDTR
+       D_MSW
+       D_TASK
+       D_CR = 35
+       D_DR = 43
+       D_TR = 51
+       D_X0 = 59 + iota - 32
+       D_X1
+       D_X2
+       D_X3
+       D_X4
+       D_X5
+       D_X6
+       D_X7
+       D_TLS    = 67
+       D_NONE   = 68
+       D_BRANCH = 69
+       D_EXTERN = 70
+       D_STATIC = 71
+       D_AUTO   = 72
+       D_PARAM  = 73
+       D_CONST  = 74
+       D_FCONST = 75
+       D_SCONST = 76
+       D_ADDR   = 77 + iota - 50
+       D_INDIR
+       D_CONST2 = D_INDIR + D_INDIR + iota - 52
+       D_LAST
+       T_TYPE    = 1 << 0
+       T_INDEX   = 1 << 1
+       T_OFFSET  = 1 << 2
+       T_FCONST  = 1 << 3
+       T_SYM     = 1 << 4
+       T_SCONST  = 1 << 5
+       T_OFFSET2 = 1 << 6
+       T_GOTYPE  = 1 << 7
+       REGARG    = -1
+       REGRET    = D_AX
+       FREGRET   = D_F0
+       REGSP     = D_SP
+       REGTMP    = D_DI
+)
diff --git a/src/cmd/internal/obj/i386/anames8.go b/src/cmd/internal/obj/i386/anames8.go
new file mode 100644 (file)
index 0000000..dd61036
--- /dev/null
@@ -0,0 +1,584 @@
+package i386
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+       "XXX",
+       "AAA",
+       "AAD",
+       "AAM",
+       "AAS",
+       "ADCB",
+       "ADCL",
+       "ADCW",
+       "ADDB",
+       "ADDL",
+       "ADDW",
+       "ADJSP",
+       "ANDB",
+       "ANDL",
+       "ANDW",
+       "ARPL",
+       "BOUNDL",
+       "BOUNDW",
+       "BSFL",
+       "BSFW",
+       "BSRL",
+       "BSRW",
+       "BTL",
+       "BTW",
+       "BTCL",
+       "BTCW",
+       "BTRL",
+       "BTRW",
+       "BTSL",
+       "BTSW",
+       "BYTE",
+       "CALL",
+       "CLC",
+       "CLD",
+       "CLI",
+       "CLTS",
+       "CMC",
+       "CMPB",
+       "CMPL",
+       "CMPW",
+       "CMPSB",
+       "CMPSL",
+       "CMPSW",
+       "DAA",
+       "DAS",
+       "DATA",
+       "DECB",
+       "DECL",
+       "DECW",
+       "DIVB",
+       "DIVL",
+       "DIVW",
+       "ENTER",
+       "GLOBL",
+       "GOK",
+       "HISTORY",
+       "HLT",
+       "IDIVB",
+       "IDIVL",
+       "IDIVW",
+       "IMULB",
+       "IMULL",
+       "IMULW",
+       "INB",
+       "INL",
+       "INW",
+       "INCB",
+       "INCL",
+       "INCW",
+       "INSB",
+       "INSL",
+       "INSW",
+       "INT",
+       "INTO",
+       "IRETL",
+       "IRETW",
+       "JCC",
+       "JCS",
+       "JCXZL",
+       "JCXZW",
+       "JEQ",
+       "JGE",
+       "JGT",
+       "JHI",
+       "JLE",
+       "JLS",
+       "JLT",
+       "JMI",
+       "JMP",
+       "JNE",
+       "JOC",
+       "JOS",
+       "JPC",
+       "JPL",
+       "JPS",
+       "LAHF",
+       "LARL",
+       "LARW",
+       "LEAL",
+       "LEAW",
+       "LEAVEL",
+       "LEAVEW",
+       "LOCK",
+       "LODSB",
+       "LODSL",
+       "LODSW",
+       "LONG",
+       "LOOP",
+       "LOOPEQ",
+       "LOOPNE",
+       "LSLL",
+       "LSLW",
+       "MOVB",
+       "MOVL",
+       "MOVW",
+       "MOVQ",
+       "MOVBLSX",
+       "MOVBLZX",
+       "MOVBWSX",
+       "MOVBWZX",
+       "MOVWLSX",
+       "MOVWLZX",
+       "MOVSB",
+       "MOVSL",
+       "MOVSW",
+       "MULB",
+       "MULL",
+       "MULW",
+       "NAME",
+       "NEGB",
+       "NEGL",
+       "NEGW",
+       "NOP",
+       "NOTB",
+       "NOTL",
+       "NOTW",
+       "ORB",
+       "ORL",
+       "ORW",
+       "OUTB",
+       "OUTL",
+       "OUTW",
+       "OUTSB",
+       "OUTSL",
+       "OUTSW",
+       "PAUSE",
+       "POPAL",
+       "POPAW",
+       "POPFL",
+       "POPFW",
+       "POPL",
+       "POPW",
+       "PUSHAL",
+       "PUSHAW",
+       "PUSHFL",
+       "PUSHFW",
+       "PUSHL",
+       "PUSHW",
+       "RCLB",
+       "RCLL",
+       "RCLW",
+       "RCRB",
+       "RCRL",
+       "RCRW",
+       "REP",
+       "REPN",
+       "RET",
+       "ROLB",
+       "ROLL",
+       "ROLW",
+       "RORB",
+       "RORL",
+       "RORW",
+       "SAHF",
+       "SALB",
+       "SALL",
+       "SALW",
+       "SARB",
+       "SARL",
+       "SARW",
+       "SBBB",
+       "SBBL",
+       "SBBW",
+       "SCASB",
+       "SCASL",
+       "SCASW",
+       "SETCC",
+       "SETCS",
+       "SETEQ",
+       "SETGE",
+       "SETGT",
+       "SETHI",
+       "SETLE",
+       "SETLS",
+       "SETLT",
+       "SETMI",
+       "SETNE",
+       "SETOC",
+       "SETOS",
+       "SETPC",
+       "SETPL",
+       "SETPS",
+       "CDQ",
+       "CWD",
+       "SHLB",
+       "SHLL",
+       "SHLW",
+       "SHRB",
+       "SHRL",
+       "SHRW",
+       "STC",
+       "STD",
+       "STI",
+       "STOSB",
+       "STOSL",
+       "STOSW",
+       "SUBB",
+       "SUBL",
+       "SUBW",
+       "SYSCALL",
+       "TESTB",
+       "TESTL",
+       "TESTW",
+       "TEXT",
+       "VERR",
+       "VERW",
+       "WAIT",
+       "WORD",
+       "XCHGB",
+       "XCHGL",
+       "XCHGW",
+       "XLAT",
+       "XORB",
+       "XORL",
+       "XORW",
+       "FMOVB",
+       "FMOVBP",
+       "FMOVD",
+       "FMOVDP",
+       "FMOVF",
+       "FMOVFP",
+       "FMOVL",
+       "FMOVLP",
+       "FMOVV",
+       "FMOVVP",
+       "FMOVW",
+       "FMOVWP",
+       "FMOVX",
+       "FMOVXP",
+       "FCOMB",
+       "FCOMBP",
+       "FCOMD",
+       "FCOMDP",
+       "FCOMDPP",
+       "FCOMF",
+       "FCOMFP",
+       "FCOMI",
+       "FCOMIP",
+       "FCOML",
+       "FCOMLP",
+       "FCOMW",
+       "FCOMWP",
+       "FUCOM",
+       "FUCOMI",
+       "FUCOMIP",
+       "FUCOMP",
+       "FUCOMPP",
+       "FADDDP",
+       "FADDW",
+       "FADDL",
+       "FADDF",
+       "FADDD",
+       "FMULDP",
+       "FMULW",
+       "FMULL",
+       "FMULF",
+       "FMULD",
+       "FSUBDP",
+       "FSUBW",
+       "FSUBL",
+       "FSUBF",
+       "FSUBD",
+       "FSUBRDP",
+       "FSUBRW",
+       "FSUBRL",
+       "FSUBRF",
+       "FSUBRD",
+       "FDIVDP",
+       "FDIVW",
+       "FDIVL",
+       "FDIVF",
+       "FDIVD",
+       "FDIVRDP",
+       "FDIVRW",
+       "FDIVRL",
+       "FDIVRF",
+       "FDIVRD",
+       "FXCHD",
+       "FFREE",
+       "FLDCW",
+       "FLDENV",
+       "FRSTOR",
+       "FSAVE",
+       "FSTCW",
+       "FSTENV",
+       "FSTSW",
+       "F2XM1",
+       "FABS",
+       "FCHS",
+       "FCLEX",
+       "FCOS",
+       "FDECSTP",
+       "FINCSTP",
+       "FINIT",
+       "FLD1",
+       "FLDL2E",
+       "FLDL2T",
+       "FLDLG2",
+       "FLDLN2",
+       "FLDPI",
+       "FLDZ",
+       "FNOP",
+       "FPATAN",
+       "FPREM",
+       "FPREM1",
+       "FPTAN",
+       "FRNDINT",
+       "FSCALE",
+       "FSIN",
+       "FSINCOS",
+       "FSQRT",
+       "FTST",
+       "FXAM",
+       "FXTRACT",
+       "FYL2X",
+       "FYL2XP1",
+       "END",
+       "DYNT_",
+       "INIT_",
+       "SIGNAME",
+       "CMPXCHGB",
+       "CMPXCHGL",
+       "CMPXCHGW",
+       "CMPXCHG8B",
+       "CPUID",
+       "RDTSC",
+       "XADDB",
+       "XADDL",
+       "XADDW",
+       "CMOVLCC",
+       "CMOVLCS",
+       "CMOVLEQ",
+       "CMOVLGE",
+       "CMOVLGT",
+       "CMOVLHI",
+       "CMOVLLE",
+       "CMOVLLS",
+       "CMOVLLT",
+       "CMOVLMI",
+       "CMOVLNE",
+       "CMOVLOC",
+       "CMOVLOS",
+       "CMOVLPC",
+       "CMOVLPL",
+       "CMOVLPS",
+       "CMOVWCC",
+       "CMOVWCS",
+       "CMOVWEQ",
+       "CMOVWGE",
+       "CMOVWGT",
+       "CMOVWHI",
+       "CMOVWLE",
+       "CMOVWLS",
+       "CMOVWLT",
+       "CMOVWMI",
+       "CMOVWNE",
+       "CMOVWOC",
+       "CMOVWOS",
+       "CMOVWPC",
+       "CMOVWPL",
+       "CMOVWPS",
+       "FCMOVCC",
+       "FCMOVCS",
+       "FCMOVEQ",
+       "FCMOVHI",
+       "FCMOVLS",
+       "FCMOVNE",
+       "FCMOVNU",
+       "FCMOVUN",
+       "LFENCE",
+       "MFENCE",
+       "SFENCE",
+       "EMMS",
+       "PREFETCHT0",
+       "PREFETCHT1",
+       "PREFETCHT2",
+       "PREFETCHNTA",
+       "BSWAPL",
+       "UNDEF",
+       "ADDPD",
+       "ADDPS",
+       "ADDSD",
+       "ADDSS",
+       "ANDNPD",
+       "ANDNPS",
+       "ANDPD",
+       "ANDPS",
+       "CMPPD",
+       "CMPPS",
+       "CMPSD",
+       "CMPSS",
+       "COMISD",
+       "COMISS",
+       "CVTPL2PD",
+       "CVTPL2PS",
+       "CVTPD2PL",
+       "CVTPD2PS",
+       "CVTPS2PL",
+       "CVTPS2PD",
+       "CVTSD2SL",
+       "CVTSD2SS",
+       "CVTSL2SD",
+       "CVTSL2SS",
+       "CVTSS2SD",
+       "CVTSS2SL",
+       "CVTTPD2PL",
+       "CVTTPS2PL",
+       "CVTTSD2SL",
+       "CVTTSS2SL",
+       "DIVPD",
+       "DIVPS",
+       "DIVSD",
+       "DIVSS",
+       "MASKMOVOU",
+       "MAXPD",
+       "MAXPS",
+       "MAXSD",
+       "MAXSS",
+       "MINPD",
+       "MINPS",
+       "MINSD",
+       "MINSS",
+       "MOVAPD",
+       "MOVAPS",
+       "MOVO",
+       "MOVOU",
+       "MOVHLPS",
+       "MOVHPD",
+       "MOVHPS",
+       "MOVLHPS",
+       "MOVLPD",
+       "MOVLPS",
+       "MOVMSKPD",
+       "MOVMSKPS",
+       "MOVNTO",
+       "MOVNTPD",
+       "MOVNTPS",
+       "MOVSD",
+       "MOVSS",
+       "MOVUPD",
+       "MOVUPS",
+       "MULPD",
+       "MULPS",
+       "MULSD",
+       "MULSS",
+       "ORPD",
+       "ORPS",
+       "PADDQ",
+       "PAND",
+       "PCMPEQB",
+       "PMAXSW",
+       "PMAXUB",
+       "PMINSW",
+       "PMINUB",
+       "PMOVMSKB",
+       "PSADBW",
+       "PSUBB",
+       "PSUBL",
+       "PSUBQ",
+       "PSUBSB",
+       "PSUBSW",
+       "PSUBUSB",
+       "PSUBUSW",
+       "PSUBW",
+       "PUNPCKHQDQ",
+       "PUNPCKLQDQ",
+       "PXOR",
+       "RCPPS",
+       "RCPSS",
+       "RSQRTPS",
+       "RSQRTSS",
+       "SQRTPD",
+       "SQRTPS",
+       "SQRTSD",
+       "SQRTSS",
+       "SUBPD",
+       "SUBPS",
+       "SUBSD",
+       "SUBSS",
+       "UCOMISD",
+       "UCOMISS",
+       "UNPCKHPD",
+       "UNPCKHPS",
+       "UNPCKLPD",
+       "UNPCKLPS",
+       "XORPD",
+       "XORPS",
+       "PSHUFHW",
+       "PSHUFL",
+       "PSHUFLW",
+       "AESENC",
+       "PINSRD",
+       "PSHUFB",
+       "USEFIELD",
+       "TYPE",
+       "FUNCDATA",
+       "PCDATA",
+       "CHECKNIL",
+       "VARDEF",
+       "VARKILL",
+       "DUFFCOPY",
+       "DUFFZERO",
+       "LAST",
+}
+
+var dnames8 = []string{
+       D_AL:     "AL",
+       D_CL:     "CL",
+       D_DL:     "DL",
+       D_BL:     "BL",
+       D_AH:     "AH",
+       D_CH:     "CH",
+       D_DH:     "DH",
+       D_BH:     "BH",
+       D_AX:     "AX",
+       D_CX:     "CX",
+       D_DX:     "DX",
+       D_BX:     "BX",
+       D_SP:     "SP",
+       D_BP:     "BP",
+       D_SI:     "SI",
+       D_DI:     "DI",
+       D_F0:     "F0",
+       D_CS:     "CS",
+       D_SS:     "SS",
+       D_DS:     "DS",
+       D_ES:     "ES",
+       D_FS:     "FS",
+       D_GS:     "GS",
+       D_GDTR:   "GDTR",
+       D_IDTR:   "IDTR",
+       D_LDTR:   "LDTR",
+       D_MSW:    "MSW",
+       D_TASK:   "TASK",
+       D_CR:     "CR",
+       D_DR:     "DR",
+       D_TR:     "TR",
+       D_X0:     "X0",
+       D_X1:     "X1",
+       D_X2:     "X2",
+       D_X3:     "X3",
+       D_X4:     "X4",
+       D_X5:     "X5",
+       D_X6:     "X6",
+       D_X7:     "X7",
+       D_TLS:    "TLS",
+       D_NONE:   "NONE",
+       D_BRANCH: "BRANCH",
+       D_EXTERN: "EXTERN",
+       D_STATIC: "STATIC",
+       D_AUTO:   "AUTO",
+       D_PARAM:  "PARAM",
+       D_CONST:  "CONST",
+       D_FCONST: "FCONST",
+       D_SCONST: "SCONST",
+       D_ADDR:   "ADDR",
+       D_INDIR:  "INDIR",
+}
diff --git a/src/cmd/internal/obj/i386/asm8.go b/src/cmd/internal/obj/i386/asm8.go
new file mode 100644 (file)
index 0000000..2c3c637
--- /dev/null
@@ -0,0 +1,4081 @@
+// Inferno utils/8l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8l/span.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.
+
+package i386
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+       "log"
+)
+
+// Instruction layout.
+
+const (
+       MaxAlign  = 32
+       FuncAlign = 16
+)
+
+type Optab struct {
+       as     int16
+       ytab   []byte
+       prefix uint8
+       op     [13]uint8
+}
+
+const (
+       Yxxx = 0 + iota
+       Ynone
+       Yi0
+       Yi1
+       Yi8
+       Yi32
+       Yiauto
+       Yal
+       Ycl
+       Yax
+       Ycx
+       Yrb
+       Yrl
+       Yrf
+       Yf0
+       Yrx
+       Ymb
+       Yml
+       Ym
+       Ybr
+       Ycol
+       Ytls
+       Ycs
+       Yss
+       Yds
+       Yes
+       Yfs
+       Ygs
+       Ygdtr
+       Yidtr
+       Yldtr
+       Ymsw
+       Ytask
+       Ycr0
+       Ycr1
+       Ycr2
+       Ycr3
+       Ycr4
+       Ycr5
+       Ycr6
+       Ycr7
+       Ydr0
+       Ydr1
+       Ydr2
+       Ydr3
+       Ydr4
+       Ydr5
+       Ydr6
+       Ydr7
+       Ytr0
+       Ytr1
+       Ytr2
+       Ytr3
+       Ytr4
+       Ytr5
+       Ytr6
+       Ytr7
+       Ymr
+       Ymm
+       Yxr
+       Yxm
+       Ymax
+       Zxxx = 0 + iota - 62
+       Zlit
+       Zlitm_r
+       Z_rp
+       Zbr
+       Zcall
+       Zcallcon
+       Zcallind
+       Zcallindreg
+       Zib_
+       Zib_rp
+       Zibo_m
+       Zil_
+       Zil_rp
+       Zilo_m
+       Zjmp
+       Zjmpcon
+       Zloop
+       Zm_o
+       Zm_r
+       Zm2_r
+       Zm_r_xm
+       Zm_r_i_xm
+       Zaut_r
+       Zo_m
+       Zpseudo
+       Zr_m
+       Zr_m_xm
+       Zr_m_i_xm
+       Zrp_
+       Z_ib
+       Z_il
+       Zm_ibo
+       Zm_ilo
+       Zib_rr
+       Zil_rr
+       Zclr
+       Zibm_r
+       Zbyte
+       Zmov
+       Zmax
+       Px  = 0
+       Pe  = 0x66
+       Pm  = 0x0f
+       Pq  = 0xff
+       Pb  = 0xfe
+       Pf2 = 0xf2
+       Pf3 = 0xf3
+)
+
+var ycover [Ymax * Ymax]uint8
+
+var reg [D_NONE]int
+
+var ynone = []uint8{
+       Ynone,
+       Ynone,
+       Zlit,
+       1,
+       0,
+}
+
+var ytext = []uint8{
+       Ymb,
+       Yi32,
+       Zpseudo,
+       1,
+       0,
+}
+
+var ynop = []uint8{
+       Ynone,
+       Ynone,
+       Zpseudo,
+       0,
+       Ynone,
+       Yiauto,
+       Zpseudo,
+       0,
+       Ynone,
+       Yml,
+       Zpseudo,
+       0,
+       Ynone,
+       Yrf,
+       Zpseudo,
+       0,
+       Yiauto,
+       Ynone,
+       Zpseudo,
+       0,
+       Ynone,
+       Yxr,
+       Zpseudo,
+       0,
+       Yml,
+       Ynone,
+       Zpseudo,
+       0,
+       Yrf,
+       Ynone,
+       Zpseudo,
+       0,
+       Yxr,
+       Ynone,
+       Zpseudo,
+       1,
+       0,
+}
+
+var yfuncdata = []uint8{
+       Yi32,
+       Ym,
+       Zpseudo,
+       0,
+       0,
+}
+
+var ypcdata = []uint8{
+       Yi32,
+       Yi32,
+       Zpseudo,
+       0,
+       0,
+}
+
+var yxorb = []uint8{
+       Yi32,
+       Yal,
+       Zib_,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var yxorl = []uint8{
+       Yi8,
+       Yml,
+       Zibo_m,
+       2,
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yaddl = []uint8{
+       Yi8,
+       Yml,
+       Zibo_m,
+       2,
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yincb = []uint8{
+       Ynone,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yincl = []uint8{
+       Ynone,
+       Yrl,
+       Z_rp,
+       1,
+       Ynone,
+       Yml,
+       Zo_m,
+       2,
+       0,
+}
+
+var ycmpb = []uint8{
+       Yal,
+       Yi32,
+       Z_ib,
+       1,
+       Ymb,
+       Yi32,
+       Zm_ibo,
+       2,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       0,
+}
+
+var ycmpl = []uint8{
+       Yml,
+       Yi8,
+       Zm_ibo,
+       2,
+       Yax,
+       Yi32,
+       Z_il,
+       1,
+       Yml,
+       Yi32,
+       Zm_ilo,
+       2,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       0,
+}
+
+var yshb = []uint8{
+       Yi1,
+       Ymb,
+       Zo_m,
+       2,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Ycx,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yshl = []uint8{
+       Yi1,
+       Yml,
+       Zo_m,
+       2,
+       Yi32,
+       Yml,
+       Zibo_m,
+       2,
+       Ycl,
+       Yml,
+       Zo_m,
+       2,
+       Ycx,
+       Yml,
+       Zo_m,
+       2,
+       0,
+}
+
+var ytestb = []uint8{
+       Yi32,
+       Yal,
+       Zib_,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var ytestl = []uint8{
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var ymovb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       Yi32,
+       Yrb,
+       Zib_rp,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       0,
+}
+
+var ymovw = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yi0,
+       Yrl,
+       Zclr,
+       1 + 2,
+       //      Yi0,    Yml,    Zibo_m, 2,      // shorter but slower AND $0,dst
+       Yi32,
+       Yrl,
+       Zil_rp,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yiauto,
+       Yrl,
+       Zaut_r,
+       1,
+       0,
+}
+
+var ymovl = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yi0,
+       Yrl,
+       Zclr,
+       1 + 2,
+       //      Yi0,    Yml,    Zibo_m, 2,      // shorter but slower AND $0,dst
+       Yi32,
+       Yrl,
+       Zil_rp,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       2, // XMM MOVD (32 bit)
+       Yxr,
+       Yml,
+       Zr_m_xm,
+       2, // XMM MOVD (32 bit)
+       Yiauto,
+       Yrl,
+       Zaut_r,
+       1,
+       0,
+}
+
+var ymovq = []uint8{
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var ym_rl = []uint8{
+       Ym,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yrl_m = []uint8{
+       Yrl,
+       Ym,
+       Zr_m,
+       1,
+       0,
+}
+
+var ymb_rl = []uint8{
+       Ymb,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yml_rl = []uint8{
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yrb_mb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       0,
+}
+
+var yrl_ml = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       0,
+}
+
+var yml_mb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var yxchg = []uint8{
+       Yax,
+       Yrl,
+       Z_rp,
+       1,
+       Yrl,
+       Yax,
+       Zrp_,
+       1,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var ydivl = []uint8{
+       Yml,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ydivb = []uint8{
+       Ymb,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var yimul = []uint8{
+       Yml,
+       Ynone,
+       Zm_o,
+       2,
+       Yi8,
+       Yrl,
+       Zib_rr,
+       1,
+       Yi32,
+       Yrl,
+       Zil_rr,
+       1,
+       0,
+}
+
+var ybyte = []uint8{
+       Yi32,
+       Ynone,
+       Zbyte,
+       1,
+       0,
+}
+
+var yin = []uint8{
+       Yi32,
+       Ynone,
+       Zib_,
+       1,
+       Ynone,
+       Ynone,
+       Zlit,
+       1,
+       0,
+}
+
+var yint = []uint8{
+       Yi32,
+       Ynone,
+       Zib_,
+       1,
+       0,
+}
+
+var ypushl = []uint8{
+       Yrl,
+       Ynone,
+       Zrp_,
+       1,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       Yi8,
+       Ynone,
+       Zib_,
+       1,
+       Yi32,
+       Ynone,
+       Zil_,
+       1,
+       0,
+}
+
+var ypopl = []uint8{
+       Ynone,
+       Yrl,
+       Z_rp,
+       1,
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var ybswap = []uint8{
+       Ynone,
+       Yrl,
+       Z_rp,
+       1,
+       0,
+}
+
+var yscond = []uint8{
+       Ynone,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yjcond = []uint8{
+       Ynone,
+       Ybr,
+       Zbr,
+       0,
+       Yi0,
+       Ybr,
+       Zbr,
+       0,
+       Yi1,
+       Ybr,
+       Zbr,
+       1,
+       0,
+}
+
+var yloop = []uint8{
+       Ynone,
+       Ybr,
+       Zloop,
+       1,
+       0,
+}
+
+var ycall = []uint8{
+       Ynone,
+       Yml,
+       Zcallindreg,
+       0,
+       Yrx,
+       Yrx,
+       Zcallindreg,
+       2,
+       Ynone,
+       Ycol,
+       Zcallind,
+       2,
+       Ynone,
+       Ybr,
+       Zcall,
+       0,
+       Ynone,
+       Yi32,
+       Zcallcon,
+       1,
+       0,
+}
+
+var yduff = []uint8{
+       Ynone,
+       Yi32,
+       Zcall,
+       1,
+       0,
+}
+
+var yjmp = []uint8{
+       Ynone,
+       Yml,
+       Zo_m,
+       2,
+       Ynone,
+       Ybr,
+       Zjmp,
+       0,
+       Ynone,
+       Yi32,
+       Zjmpcon,
+       1,
+       0,
+}
+
+var yfmvd = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvdp = []uint8{
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvf = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvx = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       0,
+}
+
+var yfmvp = []uint8{
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfcmv = []uint8{
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       0,
+}
+
+var yfadd = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfaddp = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfxch = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       0,
+}
+
+var ycompp = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2, /* botch is really f0,f1 */
+       0,
+}
+
+var ystsw = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ynone,
+       Yax,
+       Zlit,
+       1,
+       0,
+}
+
+var ystcw = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ysvrs = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ymskb = []uint8{
+       Yxr,
+       Yrl,
+       Zm_r_xm,
+       2,
+       Ymr,
+       Yrl,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxm = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcvm1 = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       Yxm,
+       Ymr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxcvm2 = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       Ymm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxmq = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxr = []uint8{
+       Yxr,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxr_ml = []uint8{
+       Yxr,
+       Yml,
+       Zr_m_xm,
+       1,
+       0,
+}
+
+var yxcmp = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcmpi = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_i_xm,
+       2,
+       0,
+}
+
+var yxmov = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       Yxr,
+       Yxm,
+       Zr_m_xm,
+       1,
+       0,
+}
+
+var yxcvfl = []uint8{
+       Yxm,
+       Yrl,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcvlf = []uint8{
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+/*
+static uchar   yxcvfq[] =
+{
+       Yxm,    Yrl,    Zm_r_xm,        2,
+       0
+};
+static uchar   yxcvqf[] =
+{
+       Yml,    Yxr,    Zm_r_xm,        2,
+       0
+};
+*/
+var yxrrl = []uint8{
+       Yxr,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yprefetch = []uint8{
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var yaes = []uint8{
+       Yxm,
+       Yxr,
+       Zlitm_r,
+       2,
+       0,
+}
+
+var yinsrd = []uint8{
+       Yml,
+       Yxr,
+       Zibm_r,
+       2,
+       0,
+}
+
+var ymshufb = []uint8{
+       Yxm,
+       Yxr,
+       Zm2_r,
+       2,
+       0,
+}
+
+var yxshuf = []uint8{
+       Yxm,
+       Yxr,
+       Zibm_r,
+       2,
+       0,
+}
+
+var optab = /* as, ytab, andproto, opcode */
+[]Optab{
+       Optab{AXXX, nil, 0, [13]uint8{}},
+       Optab{AAAA, ynone, Px, [13]uint8{0x37}},
+       Optab{AAAD, ynone, Px, [13]uint8{0xd5, 0x0a}},
+       Optab{AAAM, ynone, Px, [13]uint8{0xd4, 0x0a}},
+       Optab{AAAS, ynone, Px, [13]uint8{0x3f}},
+       Optab{AADCB, yxorb, Pb, [13]uint8{0x14, 0x80, 02, 0x10, 0x10}},
+       Optab{AADCL, yxorl, Px, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+       Optab{AADCW, yxorl, Pe, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+       Optab{AADDB, yxorb, Px, [13]uint8{0x04, 0x80, 00, 0x00, 0x02}},
+       Optab{AADDL, yaddl, Px, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+       Optab{AADDW, yaddl, Pe, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+       Optab{AADJSP, nil, 0, [13]uint8{}},
+       Optab{AANDB, yxorb, Pb, [13]uint8{0x24, 0x80, 04, 0x20, 0x22}},
+       Optab{AANDL, yxorl, Px, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+       Optab{AANDW, yxorl, Pe, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+       Optab{AARPL, yrl_ml, Px, [13]uint8{0x63}},
+       Optab{ABOUNDL, yrl_m, Px, [13]uint8{0x62}},
+       Optab{ABOUNDW, yrl_m, Pe, [13]uint8{0x62}},
+       Optab{ABSFL, yml_rl, Pm, [13]uint8{0xbc}},
+       Optab{ABSFW, yml_rl, Pq, [13]uint8{0xbc}},
+       Optab{ABSRL, yml_rl, Pm, [13]uint8{0xbd}},
+       Optab{ABSRW, yml_rl, Pq, [13]uint8{0xbd}},
+       Optab{ABTL, yml_rl, Pm, [13]uint8{0xa3}},
+       Optab{ABTW, yml_rl, Pq, [13]uint8{0xa3}},
+       Optab{ABTCL, yml_rl, Pm, [13]uint8{0xbb}},
+       Optab{ABTCW, yml_rl, Pq, [13]uint8{0xbb}},
+       Optab{ABTRL, yml_rl, Pm, [13]uint8{0xb3}},
+       Optab{ABTRW, yml_rl, Pq, [13]uint8{0xb3}},
+       Optab{ABTSL, yml_rl, Pm, [13]uint8{0xab}},
+       Optab{ABTSW, yml_rl, Pq, [13]uint8{0xab}},
+       Optab{ABYTE, ybyte, Px, [13]uint8{1}},
+       Optab{ACALL, ycall, Px, [13]uint8{0xff, 02, 0xff, 0x15, 0xe8}},
+       Optab{ACLC, ynone, Px, [13]uint8{0xf8}},
+       Optab{ACLD, ynone, Px, [13]uint8{0xfc}},
+       Optab{ACLI, ynone, Px, [13]uint8{0xfa}},
+       Optab{ACLTS, ynone, Pm, [13]uint8{0x06}},
+       Optab{ACMC, ynone, Px, [13]uint8{0xf5}},
+       Optab{ACMPB, ycmpb, Pb, [13]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
+       Optab{ACMPL, ycmpl, Px, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+       Optab{ACMPW, ycmpl, Pe, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+       Optab{ACMPSB, ynone, Pb, [13]uint8{0xa6}},
+       Optab{ACMPSL, ynone, Px, [13]uint8{0xa7}},
+       Optab{ACMPSW, ynone, Pe, [13]uint8{0xa7}},
+       Optab{ADAA, ynone, Px, [13]uint8{0x27}},
+       Optab{ADAS, ynone, Px, [13]uint8{0x2f}},
+       Optab{ADATA, nil, 0, [13]uint8{}},
+       Optab{ADECB, yincb, Pb, [13]uint8{0xfe, 01}},
+       Optab{ADECL, yincl, Px, [13]uint8{0x48, 0xff, 01}},
+       Optab{ADECW, yincl, Pe, [13]uint8{0x48, 0xff, 01}},
+       Optab{ADIVB, ydivb, Pb, [13]uint8{0xf6, 06}},
+       Optab{ADIVL, ydivl, Px, [13]uint8{0xf7, 06}},
+       Optab{ADIVW, ydivl, Pe, [13]uint8{0xf7, 06}},
+       Optab{AENTER, nil, 0, [13]uint8{}}, /* botch */
+       Optab{AGLOBL, nil, 0, [13]uint8{}},
+       Optab{AGOK, nil, 0, [13]uint8{}},
+       Optab{AHISTORY, nil, 0, [13]uint8{}},
+       Optab{AHLT, ynone, Px, [13]uint8{0xf4}},
+       Optab{AIDIVB, ydivb, Pb, [13]uint8{0xf6, 07}},
+       Optab{AIDIVL, ydivl, Px, [13]uint8{0xf7, 07}},
+       Optab{AIDIVW, ydivl, Pe, [13]uint8{0xf7, 07}},
+       Optab{AIMULB, ydivb, Pb, [13]uint8{0xf6, 05}},
+       Optab{AIMULL, yimul, Px, [13]uint8{0xf7, 05, 0x6b, 0x69}},
+       Optab{AIMULW, yimul, Pe, [13]uint8{0xf7, 05, 0x6b, 0x69}},
+       Optab{AINB, yin, Pb, [13]uint8{0xe4, 0xec}},
+       Optab{AINL, yin, Px, [13]uint8{0xe5, 0xed}},
+       Optab{AINW, yin, Pe, [13]uint8{0xe5, 0xed}},
+       Optab{AINCB, yincb, Pb, [13]uint8{0xfe, 00}},
+       Optab{AINCL, yincl, Px, [13]uint8{0x40, 0xff, 00}},
+       Optab{AINCW, yincl, Pe, [13]uint8{0x40, 0xff, 00}},
+       Optab{AINSB, ynone, Pb, [13]uint8{0x6c}},
+       Optab{AINSL, ynone, Px, [13]uint8{0x6d}},
+       Optab{AINSW, ynone, Pe, [13]uint8{0x6d}},
+       Optab{AINT, yint, Px, [13]uint8{0xcd}},
+       Optab{AINTO, ynone, Px, [13]uint8{0xce}},
+       Optab{AIRETL, ynone, Px, [13]uint8{0xcf}},
+       Optab{AIRETW, ynone, Pe, [13]uint8{0xcf}},
+       Optab{AJCC, yjcond, Px, [13]uint8{0x73, 0x83, 00}},
+       Optab{AJCS, yjcond, Px, [13]uint8{0x72, 0x82}},
+       Optab{AJCXZL, yloop, Px, [13]uint8{0xe3}},
+       Optab{AJCXZW, yloop, Px, [13]uint8{0xe3}},
+       Optab{AJEQ, yjcond, Px, [13]uint8{0x74, 0x84}},
+       Optab{AJGE, yjcond, Px, [13]uint8{0x7d, 0x8d}},
+       Optab{AJGT, yjcond, Px, [13]uint8{0x7f, 0x8f}},
+       Optab{AJHI, yjcond, Px, [13]uint8{0x77, 0x87}},
+       Optab{AJLE, yjcond, Px, [13]uint8{0x7e, 0x8e}},
+       Optab{AJLS, yjcond, Px, [13]uint8{0x76, 0x86}},
+       Optab{AJLT, yjcond, Px, [13]uint8{0x7c, 0x8c}},
+       Optab{AJMI, yjcond, Px, [13]uint8{0x78, 0x88}},
+       Optab{AJMP, yjmp, Px, [13]uint8{0xff, 04, 0xeb, 0xe9}},
+       Optab{AJNE, yjcond, Px, [13]uint8{0x75, 0x85}},
+       Optab{AJOC, yjcond, Px, [13]uint8{0x71, 0x81, 00}},
+       Optab{AJOS, yjcond, Px, [13]uint8{0x70, 0x80, 00}},
+       Optab{AJPC, yjcond, Px, [13]uint8{0x7b, 0x8b}},
+       Optab{AJPL, yjcond, Px, [13]uint8{0x79, 0x89}},
+       Optab{AJPS, yjcond, Px, [13]uint8{0x7a, 0x8a}},
+       Optab{ALAHF, ynone, Px, [13]uint8{0x9f}},
+       Optab{ALARL, yml_rl, Pm, [13]uint8{0x02}},
+       Optab{ALARW, yml_rl, Pq, [13]uint8{0x02}},
+       Optab{ALEAL, ym_rl, Px, [13]uint8{0x8d}},
+       Optab{ALEAW, ym_rl, Pe, [13]uint8{0x8d}},
+       Optab{ALEAVEL, ynone, Px, [13]uint8{0xc9}},
+       Optab{ALEAVEW, ynone, Pe, [13]uint8{0xc9}},
+       Optab{ALOCK, ynone, Px, [13]uint8{0xf0}},
+       Optab{ALODSB, ynone, Pb, [13]uint8{0xac}},
+       Optab{ALODSL, ynone, Px, [13]uint8{0xad}},
+       Optab{ALODSW, ynone, Pe, [13]uint8{0xad}},
+       Optab{ALONG, ybyte, Px, [13]uint8{4}},
+       Optab{ALOOP, yloop, Px, [13]uint8{0xe2}},
+       Optab{ALOOPEQ, yloop, Px, [13]uint8{0xe1}},
+       Optab{ALOOPNE, yloop, Px, [13]uint8{0xe0}},
+       Optab{ALSLL, yml_rl, Pm, [13]uint8{0x03}},
+       Optab{ALSLW, yml_rl, Pq, [13]uint8{0x03}},
+       Optab{AMOVB, ymovb, Pb, [13]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
+       Optab{AMOVL, ymovl, Px, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, Pe, 0x6e, Pe, 0x7e, 0}},
+       Optab{AMOVW, ymovw, Pe, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, 0}},
+       Optab{AMOVQ, ymovq, Pf3, [13]uint8{0x7e}},
+       Optab{AMOVBLSX, ymb_rl, Pm, [13]uint8{0xbe}},
+       Optab{AMOVBLZX, ymb_rl, Pm, [13]uint8{0xb6}},
+       Optab{AMOVBWSX, ymb_rl, Pq, [13]uint8{0xbe}},
+       Optab{AMOVBWZX, ymb_rl, Pq, [13]uint8{0xb6}},
+       Optab{AMOVWLSX, yml_rl, Pm, [13]uint8{0xbf}},
+       Optab{AMOVWLZX, yml_rl, Pm, [13]uint8{0xb7}},
+       Optab{AMOVSB, ynone, Pb, [13]uint8{0xa4}},
+       Optab{AMOVSL, ynone, Px, [13]uint8{0xa5}},
+       Optab{AMOVSW, ynone, Pe, [13]uint8{0xa5}},
+       Optab{AMULB, ydivb, Pb, [13]uint8{0xf6, 04}},
+       Optab{AMULL, ydivl, Px, [13]uint8{0xf7, 04}},
+       Optab{AMULW, ydivl, Pe, [13]uint8{0xf7, 04}},
+       Optab{ANAME, nil, 0, [13]uint8{}},
+       Optab{ANEGB, yscond, Px, [13]uint8{0xf6, 03}},
+       Optab{ANEGL, yscond, Px, [13]uint8{0xf7, 03}},
+       Optab{ANEGW, yscond, Pe, [13]uint8{0xf7, 03}},
+       Optab{ANOP, ynop, Px, [13]uint8{0, 0}},
+       Optab{ANOTB, yscond, Px, [13]uint8{0xf6, 02}},
+       Optab{ANOTL, yscond, Px, [13]uint8{0xf7, 02}},
+       Optab{ANOTW, yscond, Pe, [13]uint8{0xf7, 02}},
+       Optab{AORB, yxorb, Pb, [13]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
+       Optab{AORL, yxorl, Px, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+       Optab{AORW, yxorl, Pe, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+       Optab{AOUTB, yin, Pb, [13]uint8{0xe6, 0xee}},
+       Optab{AOUTL, yin, Px, [13]uint8{0xe7, 0xef}},
+       Optab{AOUTW, yin, Pe, [13]uint8{0xe7, 0xef}},
+       Optab{AOUTSB, ynone, Pb, [13]uint8{0x6e}},
+       Optab{AOUTSL, ynone, Px, [13]uint8{0x6f}},
+       Optab{AOUTSW, ynone, Pe, [13]uint8{0x6f}},
+       Optab{APAUSE, ynone, Px, [13]uint8{0xf3, 0x90}},
+       Optab{APOPAL, ynone, Px, [13]uint8{0x61}},
+       Optab{APOPAW, ynone, Pe, [13]uint8{0x61}},
+       Optab{APOPFL, ynone, Px, [13]uint8{0x9d}},
+       Optab{APOPFW, ynone, Pe, [13]uint8{0x9d}},
+       Optab{APOPL, ypopl, Px, [13]uint8{0x58, 0x8f, 00}},
+       Optab{APOPW, ypopl, Pe, [13]uint8{0x58, 0x8f, 00}},
+       Optab{APUSHAL, ynone, Px, [13]uint8{0x60}},
+       Optab{APUSHAW, ynone, Pe, [13]uint8{0x60}},
+       Optab{APUSHFL, ynone, Px, [13]uint8{0x9c}},
+       Optab{APUSHFW, ynone, Pe, [13]uint8{0x9c}},
+       Optab{APUSHL, ypushl, Px, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+       Optab{APUSHW, ypushl, Pe, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+       Optab{ARCLB, yshb, Pb, [13]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
+       Optab{ARCLL, yshl, Px, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+       Optab{ARCLW, yshl, Pe, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+       Optab{ARCRB, yshb, Pb, [13]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
+       Optab{ARCRL, yshl, Px, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+       Optab{ARCRW, yshl, Pe, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+       Optab{AREP, ynone, Px, [13]uint8{0xf3}},
+       Optab{AREPN, ynone, Px, [13]uint8{0xf2}},
+       Optab{ARET, ynone, Px, [13]uint8{0xc3}},
+       Optab{AROLB, yshb, Pb, [13]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
+       Optab{AROLL, yshl, Px, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+       Optab{AROLW, yshl, Pe, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+       Optab{ARORB, yshb, Pb, [13]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
+       Optab{ARORL, yshl, Px, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+       Optab{ARORW, yshl, Pe, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+       Optab{ASAHF, ynone, Px, [13]uint8{0x9e}},
+       Optab{ASALB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+       Optab{ASALL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASALW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASARB, yshb, Pb, [13]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
+       Optab{ASARL, yshl, Px, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+       Optab{ASARW, yshl, Pe, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+       Optab{ASBBB, yxorb, Pb, [13]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
+       Optab{ASBBL, yxorl, Px, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+       Optab{ASBBW, yxorl, Pe, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+       Optab{ASCASB, ynone, Pb, [13]uint8{0xae}},
+       Optab{ASCASL, ynone, Px, [13]uint8{0xaf}},
+       Optab{ASCASW, ynone, Pe, [13]uint8{0xaf}},
+       Optab{ASETCC, yscond, Pm, [13]uint8{0x93, 00}},
+       Optab{ASETCS, yscond, Pm, [13]uint8{0x92, 00}},
+       Optab{ASETEQ, yscond, Pm, [13]uint8{0x94, 00}},
+       Optab{ASETGE, yscond, Pm, [13]uint8{0x9d, 00}},
+       Optab{ASETGT, yscond, Pm, [13]uint8{0x9f, 00}},
+       Optab{ASETHI, yscond, Pm, [13]uint8{0x97, 00}},
+       Optab{ASETLE, yscond, Pm, [13]uint8{0x9e, 00}},
+       Optab{ASETLS, yscond, Pm, [13]uint8{0x96, 00}},
+       Optab{ASETLT, yscond, Pm, [13]uint8{0x9c, 00}},
+       Optab{ASETMI, yscond, Pm, [13]uint8{0x98, 00}},
+       Optab{ASETNE, yscond, Pm, [13]uint8{0x95, 00}},
+       Optab{ASETOC, yscond, Pm, [13]uint8{0x91, 00}},
+       Optab{ASETOS, yscond, Pm, [13]uint8{0x90, 00}},
+       Optab{ASETPC, yscond, Pm, [13]uint8{0x9b, 00}},
+       Optab{ASETPL, yscond, Pm, [13]uint8{0x99, 00}},
+       Optab{ASETPS, yscond, Pm, [13]uint8{0x9a, 00}},
+       Optab{ACDQ, ynone, Px, [13]uint8{0x99}},
+       Optab{ACWD, ynone, Pe, [13]uint8{0x99}},
+       Optab{ASHLB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+       Optab{ASHLL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASHLW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASHRB, yshb, Pb, [13]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
+       Optab{ASHRL, yshl, Px, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+       Optab{ASHRW, yshl, Pe, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+       Optab{ASTC, ynone, Px, [13]uint8{0xf9}},
+       Optab{ASTD, ynone, Px, [13]uint8{0xfd}},
+       Optab{ASTI, ynone, Px, [13]uint8{0xfb}},
+       Optab{ASTOSB, ynone, Pb, [13]uint8{0xaa}},
+       Optab{ASTOSL, ynone, Px, [13]uint8{0xab}},
+       Optab{ASTOSW, ynone, Pe, [13]uint8{0xab}},
+       Optab{ASUBB, yxorb, Pb, [13]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
+       Optab{ASUBL, yaddl, Px, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+       Optab{ASUBW, yaddl, Pe, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+       Optab{ASYSCALL, ynone, Px, [13]uint8{0xcd, 100}},
+       Optab{ATESTB, ytestb, Pb, [13]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
+       Optab{ATESTL, ytestl, Px, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+       Optab{ATESTW, ytestl, Pe, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+       Optab{ATEXT, ytext, Px, [13]uint8{}},
+       Optab{AVERR, ydivl, Pm, [13]uint8{0x00, 04}},
+       Optab{AVERW, ydivl, Pm, [13]uint8{0x00, 05}},
+       Optab{AWAIT, ynone, Px, [13]uint8{0x9b}},
+       Optab{AWORD, ybyte, Px, [13]uint8{2}},
+       Optab{AXCHGB, yml_mb, Pb, [13]uint8{0x86, 0x86}},
+       Optab{AXCHGL, yxchg, Px, [13]uint8{0x90, 0x90, 0x87, 0x87}},
+       Optab{AXCHGW, yxchg, Pe, [13]uint8{0x90, 0x90, 0x87, 0x87}},
+       Optab{AXLAT, ynone, Px, [13]uint8{0xd7}},
+       Optab{AXORB, yxorb, Pb, [13]uint8{0x34, 0x80, 06, 0x30, 0x32}},
+       Optab{AXORL, yxorl, Px, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+       Optab{AXORW, yxorl, Pe, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+       Optab{AFMOVB, yfmvx, Px, [13]uint8{0xdf, 04}},
+       Optab{AFMOVBP, yfmvp, Px, [13]uint8{0xdf, 06}},
+       Optab{AFMOVD, yfmvd, Px, [13]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
+       Optab{AFMOVDP, yfmvdp, Px, [13]uint8{0xdd, 03, 0xdd, 03}},
+       Optab{AFMOVF, yfmvf, Px, [13]uint8{0xd9, 00, 0xd9, 02}},
+       Optab{AFMOVFP, yfmvp, Px, [13]uint8{0xd9, 03}},
+       Optab{AFMOVL, yfmvf, Px, [13]uint8{0xdb, 00, 0xdb, 02}},
+       Optab{AFMOVLP, yfmvp, Px, [13]uint8{0xdb, 03}},
+       Optab{AFMOVV, yfmvx, Px, [13]uint8{0xdf, 05}},
+       Optab{AFMOVVP, yfmvp, Px, [13]uint8{0xdf, 07}},
+       Optab{AFMOVW, yfmvf, Px, [13]uint8{0xdf, 00, 0xdf, 02}},
+       Optab{AFMOVWP, yfmvp, Px, [13]uint8{0xdf, 03}},
+       Optab{AFMOVX, yfmvx, Px, [13]uint8{0xdb, 05}},
+       Optab{AFMOVXP, yfmvp, Px, [13]uint8{0xdb, 07}},
+       Optab{AFCOMB, nil, 0, [13]uint8{}},
+       Optab{AFCOMBP, nil, 0, [13]uint8{}},
+       Optab{AFCOMD, yfadd, Px, [13]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}},  /* botch */
+       Optab{AFCOMDP, yfadd, Px, [13]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
+       Optab{AFCOMDPP, ycompp, Px, [13]uint8{0xde, 03}},
+       Optab{AFCOMF, yfmvx, Px, [13]uint8{0xd8, 02}},
+       Optab{AFCOMFP, yfmvx, Px, [13]uint8{0xd8, 03}},
+       Optab{AFCOMI, yfmvx, Px, [13]uint8{0xdb, 06}},
+       Optab{AFCOMIP, yfmvx, Px, [13]uint8{0xdf, 06}},
+       Optab{AFCOML, yfmvx, Px, [13]uint8{0xda, 02}},
+       Optab{AFCOMLP, yfmvx, Px, [13]uint8{0xda, 03}},
+       Optab{AFCOMW, yfmvx, Px, [13]uint8{0xde, 02}},
+       Optab{AFCOMWP, yfmvx, Px, [13]uint8{0xde, 03}},
+       Optab{AFUCOM, ycompp, Px, [13]uint8{0xdd, 04}},
+       Optab{AFUCOMI, ycompp, Px, [13]uint8{0xdb, 05}},
+       Optab{AFUCOMIP, ycompp, Px, [13]uint8{0xdf, 05}},
+       Optab{AFUCOMP, ycompp, Px, [13]uint8{0xdd, 05}},
+       Optab{AFUCOMPP, ycompp, Px, [13]uint8{0xda, 13}},
+       Optab{AFADDDP, yfaddp, Px, [13]uint8{0xde, 00}},
+       Optab{AFADDW, yfmvx, Px, [13]uint8{0xde, 00}},
+       Optab{AFADDL, yfmvx, Px, [13]uint8{0xda, 00}},
+       Optab{AFADDF, yfmvx, Px, [13]uint8{0xd8, 00}},
+       Optab{AFADDD, yfadd, Px, [13]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
+       Optab{AFMULDP, yfaddp, Px, [13]uint8{0xde, 01}},
+       Optab{AFMULW, yfmvx, Px, [13]uint8{0xde, 01}},
+       Optab{AFMULL, yfmvx, Px, [13]uint8{0xda, 01}},
+       Optab{AFMULF, yfmvx, Px, [13]uint8{0xd8, 01}},
+       Optab{AFMULD, yfadd, Px, [13]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
+       Optab{AFSUBDP, yfaddp, Px, [13]uint8{0xde, 05}},
+       Optab{AFSUBW, yfmvx, Px, [13]uint8{0xde, 04}},
+       Optab{AFSUBL, yfmvx, Px, [13]uint8{0xda, 04}},
+       Optab{AFSUBF, yfmvx, Px, [13]uint8{0xd8, 04}},
+       Optab{AFSUBD, yfadd, Px, [13]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
+       Optab{AFSUBRDP, yfaddp, Px, [13]uint8{0xde, 04}},
+       Optab{AFSUBRW, yfmvx, Px, [13]uint8{0xde, 05}},
+       Optab{AFSUBRL, yfmvx, Px, [13]uint8{0xda, 05}},
+       Optab{AFSUBRF, yfmvx, Px, [13]uint8{0xd8, 05}},
+       Optab{AFSUBRD, yfadd, Px, [13]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
+       Optab{AFDIVDP, yfaddp, Px, [13]uint8{0xde, 07}},
+       Optab{AFDIVW, yfmvx, Px, [13]uint8{0xde, 06}},
+       Optab{AFDIVL, yfmvx, Px, [13]uint8{0xda, 06}},
+       Optab{AFDIVF, yfmvx, Px, [13]uint8{0xd8, 06}},
+       Optab{AFDIVD, yfadd, Px, [13]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
+       Optab{AFDIVRDP, yfaddp, Px, [13]uint8{0xde, 06}},
+       Optab{AFDIVRW, yfmvx, Px, [13]uint8{0xde, 07}},
+       Optab{AFDIVRL, yfmvx, Px, [13]uint8{0xda, 07}},
+       Optab{AFDIVRF, yfmvx, Px, [13]uint8{0xd8, 07}},
+       Optab{AFDIVRD, yfadd, Px, [13]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
+       Optab{AFXCHD, yfxch, Px, [13]uint8{0xd9, 01, 0xd9, 01}},
+       Optab{AFFREE, nil, 0, [13]uint8{}},
+       Optab{AFLDCW, ystcw, Px, [13]uint8{0xd9, 05, 0xd9, 05}},
+       Optab{AFLDENV, ystcw, Px, [13]uint8{0xd9, 04, 0xd9, 04}},
+       Optab{AFRSTOR, ysvrs, Px, [13]uint8{0xdd, 04, 0xdd, 04}},
+       Optab{AFSAVE, ysvrs, Px, [13]uint8{0xdd, 06, 0xdd, 06}},
+       Optab{AFSTCW, ystcw, Px, [13]uint8{0xd9, 07, 0xd9, 07}},
+       Optab{AFSTENV, ystcw, Px, [13]uint8{0xd9, 06, 0xd9, 06}},
+       Optab{AFSTSW, ystsw, Px, [13]uint8{0xdd, 07, 0xdf, 0xe0}},
+       Optab{AF2XM1, ynone, Px, [13]uint8{0xd9, 0xf0}},
+       Optab{AFABS, ynone, Px, [13]uint8{0xd9, 0xe1}},
+       Optab{AFCHS, ynone, Px, [13]uint8{0xd9, 0xe0}},
+       Optab{AFCLEX, ynone, Px, [13]uint8{0xdb, 0xe2}},
+       Optab{AFCOS, ynone, Px, [13]uint8{0xd9, 0xff}},
+       Optab{AFDECSTP, ynone, Px, [13]uint8{0xd9, 0xf6}},
+       Optab{AFINCSTP, ynone, Px, [13]uint8{0xd9, 0xf7}},
+       Optab{AFINIT, ynone, Px, [13]uint8{0xdb, 0xe3}},
+       Optab{AFLD1, ynone, Px, [13]uint8{0xd9, 0xe8}},
+       Optab{AFLDL2E, ynone, Px, [13]uint8{0xd9, 0xea}},
+       Optab{AFLDL2T, ynone, Px, [13]uint8{0xd9, 0xe9}},
+       Optab{AFLDLG2, ynone, Px, [13]uint8{0xd9, 0xec}},
+       Optab{AFLDLN2, ynone, Px, [13]uint8{0xd9, 0xed}},
+       Optab{AFLDPI, ynone, Px, [13]uint8{0xd9, 0xeb}},
+       Optab{AFLDZ, ynone, Px, [13]uint8{0xd9, 0xee}},
+       Optab{AFNOP, ynone, Px, [13]uint8{0xd9, 0xd0}},
+       Optab{AFPATAN, ynone, Px, [13]uint8{0xd9, 0xf3}},
+       Optab{AFPREM, ynone, Px, [13]uint8{0xd9, 0xf8}},
+       Optab{AFPREM1, ynone, Px, [13]uint8{0xd9, 0xf5}},
+       Optab{AFPTAN, ynone, Px, [13]uint8{0xd9, 0xf2}},
+       Optab{AFRNDINT, ynone, Px, [13]uint8{0xd9, 0xfc}},
+       Optab{AFSCALE, ynone, Px, [13]uint8{0xd9, 0xfd}},
+       Optab{AFSIN, ynone, Px, [13]uint8{0xd9, 0xfe}},
+       Optab{AFSINCOS, ynone, Px, [13]uint8{0xd9, 0xfb}},
+       Optab{AFSQRT, ynone, Px, [13]uint8{0xd9, 0xfa}},
+       Optab{AFTST, ynone, Px, [13]uint8{0xd9, 0xe4}},
+       Optab{AFXAM, ynone, Px, [13]uint8{0xd9, 0xe5}},
+       Optab{AFXTRACT, ynone, Px, [13]uint8{0xd9, 0xf4}},
+       Optab{AFYL2X, ynone, Px, [13]uint8{0xd9, 0xf1}},
+       Optab{AFYL2XP1, ynone, Px, [13]uint8{0xd9, 0xf9}},
+       Optab{AEND, nil, 0, [13]uint8{}},
+       Optab{ADYNT_, nil, 0, [13]uint8{}},
+       Optab{AINIT_, nil, 0, [13]uint8{}},
+       Optab{ASIGNAME, nil, 0, [13]uint8{}},
+       Optab{ACMPXCHGB, yrb_mb, Pm, [13]uint8{0xb0}},
+       Optab{ACMPXCHGL, yrl_ml, Pm, [13]uint8{0xb1}},
+       Optab{ACMPXCHGW, yrl_ml, Pm, [13]uint8{0xb1}},
+       Optab{ACMPXCHG8B, yscond, Pm, [13]uint8{0xc7, 01}},
+       Optab{ACPUID, ynone, Pm, [13]uint8{0xa2}},
+       Optab{ARDTSC, ynone, Pm, [13]uint8{0x31}},
+       Optab{AXADDB, yrb_mb, Pb, [13]uint8{0x0f, 0xc0}},
+       Optab{AXADDL, yrl_ml, Pm, [13]uint8{0xc1}},
+       Optab{AXADDW, yrl_ml, Pe, [13]uint8{0x0f, 0xc1}},
+       Optab{ACMOVLCC, yml_rl, Pm, [13]uint8{0x43}},
+       Optab{ACMOVLCS, yml_rl, Pm, [13]uint8{0x42}},
+       Optab{ACMOVLEQ, yml_rl, Pm, [13]uint8{0x44}},
+       Optab{ACMOVLGE, yml_rl, Pm, [13]uint8{0x4d}},
+       Optab{ACMOVLGT, yml_rl, Pm, [13]uint8{0x4f}},
+       Optab{ACMOVLHI, yml_rl, Pm, [13]uint8{0x47}},
+       Optab{ACMOVLLE, yml_rl, Pm, [13]uint8{0x4e}},
+       Optab{ACMOVLLS, yml_rl, Pm, [13]uint8{0x46}},
+       Optab{ACMOVLLT, yml_rl, Pm, [13]uint8{0x4c}},
+       Optab{ACMOVLMI, yml_rl, Pm, [13]uint8{0x48}},
+       Optab{ACMOVLNE, yml_rl, Pm, [13]uint8{0x45}},
+       Optab{ACMOVLOC, yml_rl, Pm, [13]uint8{0x41}},
+       Optab{ACMOVLOS, yml_rl, Pm, [13]uint8{0x40}},
+       Optab{ACMOVLPC, yml_rl, Pm, [13]uint8{0x4b}},
+       Optab{ACMOVLPL, yml_rl, Pm, [13]uint8{0x49}},
+       Optab{ACMOVLPS, yml_rl, Pm, [13]uint8{0x4a}},
+       Optab{ACMOVWCC, yml_rl, Pq, [13]uint8{0x43}},
+       Optab{ACMOVWCS, yml_rl, Pq, [13]uint8{0x42}},
+       Optab{ACMOVWEQ, yml_rl, Pq, [13]uint8{0x44}},
+       Optab{ACMOVWGE, yml_rl, Pq, [13]uint8{0x4d}},
+       Optab{ACMOVWGT, yml_rl, Pq, [13]uint8{0x4f}},
+       Optab{ACMOVWHI, yml_rl, Pq, [13]uint8{0x47}},
+       Optab{ACMOVWLE, yml_rl, Pq, [13]uint8{0x4e}},
+       Optab{ACMOVWLS, yml_rl, Pq, [13]uint8{0x46}},
+       Optab{ACMOVWLT, yml_rl, Pq, [13]uint8{0x4c}},
+       Optab{ACMOVWMI, yml_rl, Pq, [13]uint8{0x48}},
+       Optab{ACMOVWNE, yml_rl, Pq, [13]uint8{0x45}},
+       Optab{ACMOVWOC, yml_rl, Pq, [13]uint8{0x41}},
+       Optab{ACMOVWOS, yml_rl, Pq, [13]uint8{0x40}},
+       Optab{ACMOVWPC, yml_rl, Pq, [13]uint8{0x4b}},
+       Optab{ACMOVWPL, yml_rl, Pq, [13]uint8{0x49}},
+       Optab{ACMOVWPS, yml_rl, Pq, [13]uint8{0x4a}},
+       Optab{AFCMOVCC, yfcmv, Px, [13]uint8{0xdb, 00}},
+       Optab{AFCMOVCS, yfcmv, Px, [13]uint8{0xda, 00}},
+       Optab{AFCMOVEQ, yfcmv, Px, [13]uint8{0xda, 01}},
+       Optab{AFCMOVHI, yfcmv, Px, [13]uint8{0xdb, 02}},
+       Optab{AFCMOVLS, yfcmv, Px, [13]uint8{0xda, 02}},
+       Optab{AFCMOVNE, yfcmv, Px, [13]uint8{0xdb, 01}},
+       Optab{AFCMOVNU, yfcmv, Px, [13]uint8{0xdb, 03}},
+       Optab{AFCMOVUN, yfcmv, Px, [13]uint8{0xda, 03}},
+       Optab{ALFENCE, ynone, Pm, [13]uint8{0xae, 0xe8}},
+       Optab{AMFENCE, ynone, Pm, [13]uint8{0xae, 0xf0}},
+       Optab{ASFENCE, ynone, Pm, [13]uint8{0xae, 0xf8}},
+       Optab{AEMMS, ynone, Pm, [13]uint8{0x77}},
+       Optab{APREFETCHT0, yprefetch, Pm, [13]uint8{0x18, 01}},
+       Optab{APREFETCHT1, yprefetch, Pm, [13]uint8{0x18, 02}},
+       Optab{APREFETCHT2, yprefetch, Pm, [13]uint8{0x18, 03}},
+       Optab{APREFETCHNTA, yprefetch, Pm, [13]uint8{0x18, 00}},
+       Optab{ABSWAPL, ybswap, Pm, [13]uint8{0xc8}},
+       Optab{AUNDEF, ynone, Px, [13]uint8{0x0f, 0x0b}},
+       Optab{AADDPD, yxm, Pq, [13]uint8{0x58}},
+       Optab{AADDPS, yxm, Pm, [13]uint8{0x58}},
+       Optab{AADDSD, yxm, Pf2, [13]uint8{0x58}},
+       Optab{AADDSS, yxm, Pf3, [13]uint8{0x58}},
+       Optab{AANDNPD, yxm, Pq, [13]uint8{0x55}},
+       Optab{AANDNPS, yxm, Pm, [13]uint8{0x55}},
+       Optab{AANDPD, yxm, Pq, [13]uint8{0x54}},
+       Optab{AANDPS, yxm, Pq, [13]uint8{0x54}},
+       Optab{ACMPPD, yxcmpi, Px, [13]uint8{Pe, 0xc2}},
+       Optab{ACMPPS, yxcmpi, Pm, [13]uint8{0xc2, 0}},
+       Optab{ACMPSD, yxcmpi, Px, [13]uint8{Pf2, 0xc2}},
+       Optab{ACMPSS, yxcmpi, Px, [13]uint8{Pf3, 0xc2}},
+       Optab{ACOMISD, yxcmp, Pe, [13]uint8{0x2f}},
+       Optab{ACOMISS, yxcmp, Pm, [13]uint8{0x2f}},
+       Optab{ACVTPL2PD, yxcvm2, Px, [13]uint8{Pf3, 0xe6, Pe, 0x2a}},
+       Optab{ACVTPL2PS, yxcvm2, Pm, [13]uint8{0x5b, 0, 0x2a, 0}},
+       Optab{ACVTPD2PL, yxcvm1, Px, [13]uint8{Pf2, 0xe6, Pe, 0x2d}},
+       Optab{ACVTPD2PS, yxm, Pe, [13]uint8{0x5a}},
+       Optab{ACVTPS2PL, yxcvm1, Px, [13]uint8{Pe, 0x5b, Pm, 0x2d}},
+       Optab{ACVTPS2PD, yxm, Pm, [13]uint8{0x5a}},
+       Optab{ACVTSD2SL, yxcvfl, Pf2, [13]uint8{0x2d}},
+       Optab{ACVTSD2SS, yxm, Pf2, [13]uint8{0x5a}},
+       Optab{ACVTSL2SD, yxcvlf, Pf2, [13]uint8{0x2a}},
+       Optab{ACVTSL2SS, yxcvlf, Pf3, [13]uint8{0x2a}},
+       Optab{ACVTSS2SD, yxm, Pf3, [13]uint8{0x5a}},
+       Optab{ACVTSS2SL, yxcvfl, Pf3, [13]uint8{0x2d}},
+       Optab{ACVTTPD2PL, yxcvm1, Px, [13]uint8{Pe, 0xe6, Pe, 0x2c}},
+       Optab{ACVTTPS2PL, yxcvm1, Px, [13]uint8{Pf3, 0x5b, Pm, 0x2c}},
+       Optab{ACVTTSD2SL, yxcvfl, Pf2, [13]uint8{0x2c}},
+       Optab{ACVTTSS2SL, yxcvfl, Pf3, [13]uint8{0x2c}},
+       Optab{ADIVPD, yxm, Pe, [13]uint8{0x5e}},
+       Optab{ADIVPS, yxm, Pm, [13]uint8{0x5e}},
+       Optab{ADIVSD, yxm, Pf2, [13]uint8{0x5e}},
+       Optab{ADIVSS, yxm, Pf3, [13]uint8{0x5e}},
+       Optab{AMASKMOVOU, yxr, Pe, [13]uint8{0xf7}},
+       Optab{AMAXPD, yxm, Pe, [13]uint8{0x5f}},
+       Optab{AMAXPS, yxm, Pm, [13]uint8{0x5f}},
+       Optab{AMAXSD, yxm, Pf2, [13]uint8{0x5f}},
+       Optab{AMAXSS, yxm, Pf3, [13]uint8{0x5f}},
+       Optab{AMINPD, yxm, Pe, [13]uint8{0x5d}},
+       Optab{AMINPS, yxm, Pm, [13]uint8{0x5d}},
+       Optab{AMINSD, yxm, Pf2, [13]uint8{0x5d}},
+       Optab{AMINSS, yxm, Pf3, [13]uint8{0x5d}},
+       Optab{AMOVAPD, yxmov, Pe, [13]uint8{0x28, 0x29}},
+       Optab{AMOVAPS, yxmov, Pm, [13]uint8{0x28, 0x29}},
+       Optab{AMOVO, yxmov, Pe, [13]uint8{0x6f, 0x7f}},
+       Optab{AMOVOU, yxmov, Pf3, [13]uint8{0x6f, 0x7f}},
+       Optab{AMOVHLPS, yxr, Pm, [13]uint8{0x12}},
+       Optab{AMOVHPD, yxmov, Pe, [13]uint8{0x16, 0x17}},
+       Optab{AMOVHPS, yxmov, Pm, [13]uint8{0x16, 0x17}},
+       Optab{AMOVLHPS, yxr, Pm, [13]uint8{0x16}},
+       Optab{AMOVLPD, yxmov, Pe, [13]uint8{0x12, 0x13}},
+       Optab{AMOVLPS, yxmov, Pm, [13]uint8{0x12, 0x13}},
+       Optab{AMOVMSKPD, yxrrl, Pq, [13]uint8{0x50}},
+       Optab{AMOVMSKPS, yxrrl, Pm, [13]uint8{0x50}},
+       Optab{AMOVNTO, yxr_ml, Pe, [13]uint8{0xe7}},
+       Optab{AMOVNTPD, yxr_ml, Pe, [13]uint8{0x2b}},
+       Optab{AMOVNTPS, yxr_ml, Pm, [13]uint8{0x2b}},
+       Optab{AMOVSD, yxmov, Pf2, [13]uint8{0x10, 0x11}},
+       Optab{AMOVSS, yxmov, Pf3, [13]uint8{0x10, 0x11}},
+       Optab{AMOVUPD, yxmov, Pe, [13]uint8{0x10, 0x11}},
+       Optab{AMOVUPS, yxmov, Pm, [13]uint8{0x10, 0x11}},
+       Optab{AMULPD, yxm, Pe, [13]uint8{0x59}},
+       Optab{AMULPS, yxm, Ym, [13]uint8{0x59}},
+       Optab{AMULSD, yxm, Pf2, [13]uint8{0x59}},
+       Optab{AMULSS, yxm, Pf3, [13]uint8{0x59}},
+       Optab{AORPD, yxm, Pq, [13]uint8{0x56}},
+       Optab{AORPS, yxm, Pm, [13]uint8{0x56}},
+       Optab{APADDQ, yxm, Pe, [13]uint8{0xd4}},
+       Optab{APAND, yxm, Pe, [13]uint8{0xdb}},
+       Optab{APCMPEQB, yxmq, Pe, [13]uint8{0x74}},
+       Optab{APMAXSW, yxm, Pe, [13]uint8{0xee}},
+       Optab{APMAXUB, yxm, Pe, [13]uint8{0xde}},
+       Optab{APMINSW, yxm, Pe, [13]uint8{0xea}},
+       Optab{APMINUB, yxm, Pe, [13]uint8{0xda}},
+       Optab{APMOVMSKB, ymskb, Px, [13]uint8{Pe, 0xd7, 0xd7}},
+       Optab{APSADBW, yxm, Pq, [13]uint8{0xf6}},
+       Optab{APSUBB, yxm, Pe, [13]uint8{0xf8}},
+       Optab{APSUBL, yxm, Pe, [13]uint8{0xfa}},
+       Optab{APSUBQ, yxm, Pe, [13]uint8{0xfb}},
+       Optab{APSUBSB, yxm, Pe, [13]uint8{0xe8}},
+       Optab{APSUBSW, yxm, Pe, [13]uint8{0xe9}},
+       Optab{APSUBUSB, yxm, Pe, [13]uint8{0xd8}},
+       Optab{APSUBUSW, yxm, Pe, [13]uint8{0xd9}},
+       Optab{APSUBW, yxm, Pe, [13]uint8{0xf9}},
+       Optab{APUNPCKHQDQ, yxm, Pe, [13]uint8{0x6d}},
+       Optab{APUNPCKLQDQ, yxm, Pe, [13]uint8{0x6c}},
+       Optab{APXOR, yxm, Pe, [13]uint8{0xef}},
+       Optab{ARCPPS, yxm, Pm, [13]uint8{0x53}},
+       Optab{ARCPSS, yxm, Pf3, [13]uint8{0x53}},
+       Optab{ARSQRTPS, yxm, Pm, [13]uint8{0x52}},
+       Optab{ARSQRTSS, yxm, Pf3, [13]uint8{0x52}},
+       Optab{ASQRTPD, yxm, Pe, [13]uint8{0x51}},
+       Optab{ASQRTPS, yxm, Pm, [13]uint8{0x51}},
+       Optab{ASQRTSD, yxm, Pf2, [13]uint8{0x51}},
+       Optab{ASQRTSS, yxm, Pf3, [13]uint8{0x51}},
+       Optab{ASUBPD, yxm, Pe, [13]uint8{0x5c}},
+       Optab{ASUBPS, yxm, Pm, [13]uint8{0x5c}},
+       Optab{ASUBSD, yxm, Pf2, [13]uint8{0x5c}},
+       Optab{ASUBSS, yxm, Pf3, [13]uint8{0x5c}},
+       Optab{AUCOMISD, yxcmp, Pe, [13]uint8{0x2e}},
+       Optab{AUCOMISS, yxcmp, Pm, [13]uint8{0x2e}},
+       Optab{AUNPCKHPD, yxm, Pe, [13]uint8{0x15}},
+       Optab{AUNPCKHPS, yxm, Pm, [13]uint8{0x15}},
+       Optab{AUNPCKLPD, yxm, Pe, [13]uint8{0x14}},
+       Optab{AUNPCKLPS, yxm, Pm, [13]uint8{0x14}},
+       Optab{AXORPD, yxm, Pe, [13]uint8{0x57}},
+       Optab{AXORPS, yxm, Pm, [13]uint8{0x57}},
+       Optab{APSHUFHW, yxshuf, Pf3, [13]uint8{0x70, 00}},
+       Optab{APSHUFL, yxshuf, Pq, [13]uint8{0x70, 00}},
+       Optab{APSHUFLW, yxshuf, Pf2, [13]uint8{0x70, 00}},
+       Optab{AAESENC, yaes, Pq, [13]uint8{0x38, 0xdc, 0}},
+       Optab{APINSRD, yinsrd, Pq, [13]uint8{0x3a, 0x22, 00}},
+       Optab{APSHUFB, ymshufb, Pq, [13]uint8{0x38, 0x00}},
+       Optab{AUSEFIELD, ynop, Px, [13]uint8{0, 0}},
+       Optab{ATYPE, nil, 0, [13]uint8{}},
+       Optab{AFUNCDATA, yfuncdata, Px, [13]uint8{0, 0}},
+       Optab{APCDATA, ypcdata, Px, [13]uint8{0, 0}},
+       Optab{ACHECKNIL, nil, 0, [13]uint8{}},
+       Optab{AVARDEF, nil, 0, [13]uint8{}},
+       Optab{AVARKILL, nil, 0, [13]uint8{}},
+       Optab{ADUFFCOPY, yduff, Px, [13]uint8{0xe8}},
+       Optab{ADUFFZERO, yduff, Px, [13]uint8{0xe8}},
+       Optab{0, nil, 0, [13]uint8{}},
+}
+
+// single-instruction no-ops of various lengths.
+// constructed by hand and disassembled with gdb to verify.
+// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
+var nop = [][16]uint8{
+       [16]uint8{0x90},
+       [16]uint8{0x66, 0x90},
+       [16]uint8{0x0F, 0x1F, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x40, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
+       [16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+       [16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+}
+
+// Native Client rejects the repeated 0x66 prefix.
+// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+func fillnop(p []byte, n int) {
+
+       var m int
+
+       for n > 0 {
+               m = n
+               if m > len(nop) {
+                       m = len(nop)
+               }
+               copy(p[:m], nop[m-1][:m])
+               p = p[m:]
+               n -= m
+       }
+}
+
+func naclpad(ctxt *obj.Link, s *obj.LSym, c int32, pad int32) int32 {
+       obj.Symgrow(ctxt, s, int64(c)+int64(pad))
+       fillnop(s.P[c:], int(pad))
+       return c + pad
+}
+
+func span8(ctxt *obj.Link, s *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var c int32
+       var v int32
+       var loop int32
+       var bp []byte
+       var n int
+       var m int
+       var i int
+
+       ctxt.Cursym = s
+
+       if s.Text == nil || s.Text.Link == nil {
+               return
+       }
+
+       if ycover[0] == 0 {
+               instinit()
+       }
+
+       for p = s.Text; p != nil; p = p.Link {
+               n = 0
+               if p.To.Type == D_BRANCH {
+                       if p.Pcond == nil {
+                               p.Pcond = p
+                       }
+               }
+               q = p.Pcond
+               if q != nil {
+                       if q.Back != 2 {
+                               n = 1
+                       }
+               }
+               p.Back = uint8(n)
+               if p.As == AADJSP {
+                       p.To.Type = D_SP
+                       v = int32(-p.From.Offset)
+                       p.From.Offset = int64(v)
+                       p.As = AADDL
+                       if v < 0 {
+                               p.As = ASUBL
+                               v = -v
+                               p.From.Offset = int64(v)
+                       }
+
+                       if v == 0 {
+                               p.As = ANOP
+                       }
+               }
+       }
+
+       for p = s.Text; p != nil; p = p.Link {
+               p.Back = 2 // use short branches first time through
+               q = p.Pcond
+               if q != nil && (q.Back&2 != 0) {
+                       p.Back |= 1 // backward jump
+               }
+
+               if p.As == AADJSP {
+
+                       p.To.Type = D_SP
+                       v = int32(-p.From.Offset)
+                       p.From.Offset = int64(v)
+                       p.As = AADDL
+                       if v < 0 {
+                               p.As = ASUBL
+                               v = -v
+                               p.From.Offset = int64(v)
+                       }
+
+                       if v == 0 {
+                               p.As = ANOP
+                       }
+               }
+       }
+
+       n = 0
+       for {
+               loop = 0
+               for i = 0; i < len(s.R); i++ {
+                       s.R[i] = obj.Reloc{}
+               }
+               s.R = s.R[:0]
+               s.P = s.P[:0]
+               c = 0
+               for p = s.Text; p != nil; p = p.Link {
+                       if ctxt.Headtype == obj.Hnacl && p.Isize > 0 {
+                               var deferreturn *obj.LSym
+
+                               if deferreturn == nil {
+                                       deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+                               }
+
+                               // pad everything to avoid crossing 32-byte boundary
+                               if c>>5 != (c+int32(p.Isize)-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // pad call deferreturn to start at 32-byte boundary
+                               // so that subtracting 5 in jmpdefer will jump back
+                               // to that boundary and rerun the call.
+                               if p.As == ACALL && p.To.Sym == deferreturn {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // pad call to end at 32-byte boundary
+                               if p.As == ACALL {
+
+                                       c = naclpad(ctxt, s, c, -(c+int32(p.Isize))&31)
+                               }
+
+                               // the linker treats REP and STOSQ as different instructions
+                               // but in fact the REP is a prefix on the STOSQ.
+                               // make sure REP has room for 2 more bytes, so that
+                               // padding will not be inserted before the next instruction.
+                               if p.As == AREP && c>>5 != (c+3-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // same for LOCK.
+                               // various instructions follow; the longest is 4 bytes.
+                               // give ourselves 8 bytes so as to avoid surprises.
+                               if p.As == ALOCK && c>>5 != (c+8-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+                       }
+
+                       p.Pc = int64(c)
+
+                       // process forward jumps to p
+                       for q = p.Comefrom; q != nil; q = q.Forwd {
+
+                               v = int32(p.Pc - (q.Pc + int64(q.Mark)))
+                               if q.Back&2 != 0 { // short
+                                       if v > 127 {
+                                               loop++
+                                               q.Back ^= 2
+                                       }
+
+                                       if q.As == AJCXZW {
+                                               s.P[q.Pc+2] = byte(v)
+                                       } else {
+
+                                               s.P[q.Pc+1] = byte(v)
+                                       }
+                               } else {
+
+                                       bp = s.P[q.Pc+int64(q.Mark)-4:]
+                                       bp[0] = byte(v)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 8)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 16)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 24)
+                               }
+                       }
+
+                       p.Comefrom = nil
+
+                       p.Pc = int64(c)
+                       asmins(ctxt, p)
+                       m = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+                       if int(p.Isize) != m {
+                               p.Isize = uint8(m)
+                               loop++
+                       }
+
+                       obj.Symgrow(ctxt, s, p.Pc+int64(m))
+                       copy(s.P[p.Pc:][:m], ctxt.And[:m])
+                       p.Mark = uint16(m)
+                       c += int32(m)
+               }
+
+               n++
+               if n > 20 {
+                       ctxt.Diag("span must be looping")
+                       log.Fatalf("bad code")
+               }
+               if !(loop != 0) {
+                       break
+               }
+       }
+
+       if ctxt.Headtype == obj.Hnacl {
+               c = naclpad(ctxt, s, c, -c&31)
+       }
+       c += -c & (FuncAlign - 1)
+       s.Size = int64(c)
+
+       if false { /* debug['a'] > 1 */
+               fmt.Printf("span1 %s %d (%d tries)\n %.6x", s.Name, s.Size, n, 0)
+               for i = 0; i < len(s.P); i++ {
+                       fmt.Printf(" %.2x", s.P[i])
+                       if i%16 == 15 {
+                               fmt.Printf("\n  %.6x", uint(i+1))
+                       }
+               }
+
+               if i%16 != 0 {
+                       fmt.Printf("\n")
+               }
+
+               for i = 0; i < len(s.R); i++ {
+                       var r *obj.Reloc
+
+                       r = &s.R[i]
+                       fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add)
+               }
+       }
+}
+
+func instinit() {
+       var i int
+
+       for i = 1; optab[i].as != 0; i++ {
+               if i != int(optab[i].as) {
+                       log.Fatalf("phase error in optab: at %v found %v", Aconv(i), Aconv(int(optab[i].as)))
+               }
+       }
+
+       for i = 0; i < Ymax; i++ {
+               ycover[i*Ymax+i] = 1
+       }
+
+       ycover[Yi0*Ymax+Yi8] = 1
+       ycover[Yi1*Ymax+Yi8] = 1
+
+       ycover[Yi0*Ymax+Yi32] = 1
+       ycover[Yi1*Ymax+Yi32] = 1
+       ycover[Yi8*Ymax+Yi32] = 1
+
+       ycover[Yal*Ymax+Yrb] = 1
+       ycover[Ycl*Ymax+Yrb] = 1
+       ycover[Yax*Ymax+Yrb] = 1
+       ycover[Ycx*Ymax+Yrb] = 1
+       ycover[Yrx*Ymax+Yrb] = 1
+
+       ycover[Yax*Ymax+Yrx] = 1
+       ycover[Ycx*Ymax+Yrx] = 1
+
+       ycover[Yax*Ymax+Yrl] = 1
+       ycover[Ycx*Ymax+Yrl] = 1
+       ycover[Yrx*Ymax+Yrl] = 1
+
+       ycover[Yf0*Ymax+Yrf] = 1
+
+       ycover[Yal*Ymax+Ymb] = 1
+       ycover[Ycl*Ymax+Ymb] = 1
+       ycover[Yax*Ymax+Ymb] = 1
+       ycover[Ycx*Ymax+Ymb] = 1
+       ycover[Yrx*Ymax+Ymb] = 1
+       ycover[Yrb*Ymax+Ymb] = 1
+       ycover[Ym*Ymax+Ymb] = 1
+
+       ycover[Yax*Ymax+Yml] = 1
+       ycover[Ycx*Ymax+Yml] = 1
+       ycover[Yrx*Ymax+Yml] = 1
+       ycover[Yrl*Ymax+Yml] = 1
+       ycover[Ym*Ymax+Yml] = 1
+
+       ycover[Yax*Ymax+Ymm] = 1
+       ycover[Ycx*Ymax+Ymm] = 1
+       ycover[Yrx*Ymax+Ymm] = 1
+       ycover[Yrl*Ymax+Ymm] = 1
+       ycover[Ym*Ymax+Ymm] = 1
+       ycover[Ymr*Ymax+Ymm] = 1
+
+       ycover[Ym*Ymax+Yxm] = 1
+       ycover[Yxr*Ymax+Yxm] = 1
+
+       for i = 0; i < D_NONE; i++ {
+               reg[i] = -1
+               if i >= D_AL && i <= D_BH {
+                       reg[i] = (i - D_AL) & 7
+               }
+               if i >= D_AX && i <= D_DI {
+                       reg[i] = (i - D_AX) & 7
+               }
+               if i >= D_F0 && i <= D_F0+7 {
+                       reg[i] = (i - D_F0) & 7
+               }
+               if i >= D_X0 && i <= D_X0+7 {
+                       reg[i] = (i - D_X0) & 7
+               }
+       }
+}
+
+func prefixof(ctxt *obj.Link, a *obj.Addr) int {
+       switch a.Type {
+       case D_INDIR + D_CS:
+               return 0x2e
+
+       case D_INDIR + D_DS:
+               return 0x3e
+
+       case D_INDIR + D_ES:
+               return 0x26
+
+       case D_INDIR + D_FS:
+               return 0x64
+
+       case D_INDIR + D_GS:
+               return 0x65
+
+               // NOTE: Systems listed here should be only systems that
+       // support direct TLS references like 8(TLS) implemented as
+       // direct references from FS or GS. Systems that require
+       // the initial-exec model, where you load the TLS base into
+       // a register and then index from that register, do not reach
+       // this code and should not be listed.
+       case D_INDIR + D_TLS:
+               switch ctxt.Headtype {
+
+               default:
+                       log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
+
+               case obj.Hdarwin,
+                       obj.Hdragonfly,
+                       obj.Hfreebsd,
+                       obj.Hnetbsd,
+                       obj.Hopenbsd:
+                       return 0x65 // GS
+               }
+       }
+
+       return 0
+}
+
+func oclass(a *obj.Addr) int {
+       var v int32
+
+       if (a.Type >= D_INDIR && a.Type < 2*D_INDIR) || a.Index != D_NONE {
+               if a.Index != D_NONE && a.Scale == 0 {
+                       if a.Type == D_ADDR {
+                               switch a.Index {
+                               case D_EXTERN,
+                                       D_STATIC:
+                                       return Yi32
+
+                               case D_AUTO,
+                                       D_PARAM:
+                                       return Yiauto
+                               }
+
+                               return Yxxx
+                       }
+
+                       //if(a->type == D_INDIR+D_ADDR)
+                       //      print("*Ycol\n");
+                       return Ycol
+               }
+
+               return Ym
+       }
+
+       switch a.Type {
+       case D_AL:
+               return Yal
+
+       case D_AX:
+               return Yax
+
+       case D_CL,
+               D_DL,
+               D_BL,
+               D_AH,
+               D_CH,
+               D_DH,
+               D_BH:
+               return Yrb
+
+       case D_CX:
+               return Ycx
+
+       case D_DX,
+               D_BX:
+               return Yrx
+
+       case D_SP,
+               D_BP,
+               D_SI,
+               D_DI:
+               return Yrl
+
+       case D_F0 + 0:
+               return Yf0
+
+       case D_F0 + 1,
+               D_F0 + 2,
+               D_F0 + 3,
+               D_F0 + 4,
+               D_F0 + 5,
+               D_F0 + 6,
+               D_F0 + 7:
+               return Yrf
+
+       case D_X0 + 0,
+               D_X0 + 1,
+               D_X0 + 2,
+               D_X0 + 3,
+               D_X0 + 4,
+               D_X0 + 5,
+               D_X0 + 6,
+               D_X0 + 7:
+               return Yxr
+
+       case D_NONE:
+               return Ynone
+
+       case D_CS:
+               return Ycs
+       case D_SS:
+               return Yss
+       case D_DS:
+               return Yds
+       case D_ES:
+               return Yes
+       case D_FS:
+               return Yfs
+       case D_GS:
+               return Ygs
+       case D_TLS:
+               return Ytls
+
+       case D_GDTR:
+               return Ygdtr
+       case D_IDTR:
+               return Yidtr
+       case D_LDTR:
+               return Yldtr
+       case D_MSW:
+               return Ymsw
+       case D_TASK:
+               return Ytask
+
+       case D_CR + 0:
+               return Ycr0
+       case D_CR + 1:
+               return Ycr1
+       case D_CR + 2:
+               return Ycr2
+       case D_CR + 3:
+               return Ycr3
+       case D_CR + 4:
+               return Ycr4
+       case D_CR + 5:
+               return Ycr5
+       case D_CR + 6:
+               return Ycr6
+       case D_CR + 7:
+               return Ycr7
+
+       case D_DR + 0:
+               return Ydr0
+       case D_DR + 1:
+               return Ydr1
+       case D_DR + 2:
+               return Ydr2
+       case D_DR + 3:
+               return Ydr3
+       case D_DR + 4:
+               return Ydr4
+       case D_DR + 5:
+               return Ydr5
+       case D_DR + 6:
+               return Ydr6
+       case D_DR + 7:
+               return Ydr7
+
+       case D_TR + 0:
+               return Ytr0
+       case D_TR + 1:
+               return Ytr1
+       case D_TR + 2:
+               return Ytr2
+       case D_TR + 3:
+               return Ytr3
+       case D_TR + 4:
+               return Ytr4
+       case D_TR + 5:
+               return Ytr5
+       case D_TR + 6:
+               return Ytr6
+       case D_TR + 7:
+               return Ytr7
+
+       case D_EXTERN,
+               D_STATIC,
+               D_AUTO,
+               D_PARAM:
+               return Ym
+
+       case D_CONST,
+               D_CONST2,
+               D_ADDR:
+               if a.Sym == nil {
+                       v = int32(a.Offset)
+                       if v == 0 {
+                               return Yi0
+                       }
+                       if v == 1 {
+                               return Yi1
+                       }
+                       if v >= -128 && v <= 127 {
+                               return Yi8
+                       }
+               }
+
+               return Yi32
+
+       case D_BRANCH:
+               return Ybr
+       }
+
+       return Yxxx
+}
+
+func asmidx(ctxt *obj.Link, scale int, index int, base int) {
+       var i int
+
+       switch index {
+       default:
+               goto bad
+
+       case D_NONE:
+               i = 4 << 3
+               goto bas
+
+       case D_AX,
+               D_CX,
+               D_DX,
+               D_BX,
+               D_BP,
+               D_SI,
+               D_DI:
+               i = reg[index] << 3
+               break
+       }
+
+       switch scale {
+       default:
+               goto bad
+
+       case 1:
+               break
+
+       case 2:
+               i |= 1 << 6
+
+       case 4:
+               i |= 2 << 6
+
+       case 8:
+               i |= 3 << 6
+               break
+       }
+
+bas:
+       switch base {
+       default:
+               goto bad
+
+       case D_NONE: /* must be mod=00 */
+               i |= 5
+
+       case D_AX,
+               D_CX,
+               D_DX,
+               D_BX,
+               D_SP,
+               D_BP,
+               D_SI,
+               D_DI:
+               i |= reg[base]
+               break
+       }
+
+       ctxt.Andptr[0] = byte(i)
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return
+
+bad:
+       ctxt.Diag("asmidx: bad address %d,%d,%d", scale, index, base)
+       ctxt.Andptr[0] = 0
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return
+}
+
+func put4(ctxt *obj.Link, v int32) {
+       ctxt.Andptr[0] = byte(v)
+       ctxt.Andptr[1] = byte(v >> 8)
+       ctxt.Andptr[2] = byte(v >> 16)
+       ctxt.Andptr[3] = byte(v >> 24)
+       ctxt.Andptr = ctxt.Andptr[4:]
+}
+
+func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+       var v int64
+       var rel obj.Reloc
+       var r *obj.Reloc
+
+       v = int64(vaddr(ctxt, p, a, &rel))
+       if rel.Siz != 0 {
+               if rel.Siz != 4 {
+                       ctxt.Diag("bad reloc")
+               }
+               r = obj.Addrel(ctxt.Cursym)
+               *r = rel
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+       }
+
+       put4(ctxt, int32(v))
+}
+
+func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int32 {
+       var t int
+       var v int32
+       var s *obj.LSym
+
+       if r != nil {
+               *r = obj.Reloc{}
+       }
+
+       t = int(a.Type)
+       v = int32(a.Offset)
+       if t == D_ADDR {
+               t = int(a.Index)
+       }
+       switch t {
+       case D_STATIC,
+               D_EXTERN:
+               s = a.Sym
+               if s != nil {
+                       if r == nil {
+                               ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+                               log.Fatalf("bad code")
+                       }
+
+                       r.Type = obj.R_ADDR
+                       r.Siz = 4
+                       r.Off = -1
+                       r.Sym = s
+                       r.Add = int64(v)
+                       v = 0
+               }
+
+       case D_INDIR + D_TLS:
+               if r == nil {
+                       ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+                       log.Fatalf("bad code")
+               }
+
+               r.Type = obj.R_TLS_LE
+               r.Siz = 4
+               r.Off = -1 // caller must fill in
+               r.Add = int64(v)
+               v = 0
+               break
+       }
+
+       return v
+}
+
+func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int) {
+       var v int32
+       var t int
+       var scale int
+       var rel obj.Reloc
+
+       v = int32(a.Offset)
+       t = int(a.Type)
+       rel.Siz = 0
+       if a.Index != D_NONE && a.Index != D_TLS {
+               if t < D_INDIR || t >= 2*D_INDIR {
+                       switch t {
+                       default:
+                               goto bad
+
+                       case D_STATIC,
+                               D_EXTERN:
+                               t = D_NONE
+                               v = vaddr(ctxt, p, a, &rel)
+
+                       case D_AUTO,
+                               D_PARAM:
+                               t = D_SP
+                               break
+                       }
+               } else {
+
+                       t -= D_INDIR
+               }
+
+               if t == D_NONE {
+                       ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       goto putrelv
+               }
+
+               if v == 0 && rel.Siz == 0 && t != D_BP {
+                       ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       return
+               }
+
+               if v >= -128 && v < 128 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmidx(ctxt, int(a.Scale), int(a.Index), t)
+               goto putrelv
+       }
+
+       if t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7 {
+               if v != 0 {
+                       goto bad
+               }
+               ctxt.Andptr[0] = byte(3<<6 | reg[t]<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               return
+       }
+
+       scale = int(a.Scale)
+       if t < D_INDIR || t >= 2*D_INDIR {
+               switch a.Type {
+               default:
+                       goto bad
+
+               case D_STATIC,
+                       D_EXTERN:
+                       t = D_NONE
+                       v = vaddr(ctxt, p, a, &rel)
+
+               case D_AUTO,
+                       D_PARAM:
+                       t = D_SP
+                       break
+               }
+
+               scale = 1
+       } else {
+
+               t -= D_INDIR
+       }
+       if t == D_TLS {
+               v = vaddr(ctxt, p, a, &rel)
+       }
+
+       if t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS {
+               ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               goto putrelv
+       }
+
+       if t == D_SP {
+               if v == 0 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, scale, D_NONE, t)
+                       return
+               }
+
+               if v >= -128 && v < 128 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, scale, D_NONE, t)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmidx(ctxt, scale, D_NONE, t)
+               goto putrelv
+       }
+
+       if t >= D_AX && t <= D_DI {
+               if a.Index == D_TLS {
+                       rel = obj.Reloc{}
+                       rel.Type = obj.R_TLS_IE
+                       rel.Siz = 4
+                       rel.Sym = nil
+                       rel.Add = int64(v)
+                       v = 0
+               }
+
+               if v == 0 && rel.Siz == 0 && t != D_BP {
+                       ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               if v >= -128 && v < 128 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr[1] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[2:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               goto putrelv
+       }
+
+       goto bad
+
+putrelv:
+       if rel.Siz != 0 {
+               var r *obj.Reloc
+
+               if rel.Siz != 4 {
+                       ctxt.Diag("bad rel")
+                       goto bad
+               }
+
+               r = obj.Addrel(ctxt.Cursym)
+               *r = rel
+               r.Off = int32(ctxt.Curp.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+       }
+
+       put4(ctxt, v)
+       return
+
+bad:
+       ctxt.Diag("asmand: bad address %v", Dconv(p, 0, a))
+       return
+}
+
+const (
+       E = 0xff
+)
+
+var ymovtab = []uint8{
+       /* push */
+       APUSHL,
+       Ycs,
+       Ynone,
+       0,
+       0x0e,
+       E,
+       0,
+       0,
+       APUSHL,
+       Yss,
+       Ynone,
+       0,
+       0x16,
+       E,
+       0,
+       0,
+       APUSHL,
+       Yds,
+       Ynone,
+       0,
+       0x1e,
+       E,
+       0,
+       0,
+       APUSHL,
+       Yes,
+       Ynone,
+       0,
+       0x06,
+       E,
+       0,
+       0,
+       APUSHL,
+       Yfs,
+       Ynone,
+       0,
+       0x0f,
+       0xa0,
+       E,
+       0,
+       APUSHL,
+       Ygs,
+       Ynone,
+       0,
+       0x0f,
+       0xa8,
+       E,
+       0,
+       APUSHW,
+       Ycs,
+       Ynone,
+       0,
+       Pe,
+       0x0e,
+       E,
+       0,
+       APUSHW,
+       Yss,
+       Ynone,
+       0,
+       Pe,
+       0x16,
+       E,
+       0,
+       APUSHW,
+       Yds,
+       Ynone,
+       0,
+       Pe,
+       0x1e,
+       E,
+       0,
+       APUSHW,
+       Yes,
+       Ynone,
+       0,
+       Pe,
+       0x06,
+       E,
+       0,
+       APUSHW,
+       Yfs,
+       Ynone,
+       0,
+       Pe,
+       0x0f,
+       0xa0,
+       E,
+       APUSHW,
+       Ygs,
+       Ynone,
+       0,
+       Pe,
+       0x0f,
+       0xa8,
+       E,
+
+       /* pop */
+       APOPL,
+       Ynone,
+       Yds,
+       0,
+       0x1f,
+       E,
+       0,
+       0,
+       APOPL,
+       Ynone,
+       Yes,
+       0,
+       0x07,
+       E,
+       0,
+       0,
+       APOPL,
+       Ynone,
+       Yss,
+       0,
+       0x17,
+       E,
+       0,
+       0,
+       APOPL,
+       Ynone,
+       Yfs,
+       0,
+       0x0f,
+       0xa1,
+       E,
+       0,
+       APOPL,
+       Ynone,
+       Ygs,
+       0,
+       0x0f,
+       0xa9,
+       E,
+       0,
+       APOPW,
+       Ynone,
+       Yds,
+       0,
+       Pe,
+       0x1f,
+       E,
+       0,
+       APOPW,
+       Ynone,
+       Yes,
+       0,
+       Pe,
+       0x07,
+       E,
+       0,
+       APOPW,
+       Ynone,
+       Yss,
+       0,
+       Pe,
+       0x17,
+       E,
+       0,
+       APOPW,
+       Ynone,
+       Yfs,
+       0,
+       Pe,
+       0x0f,
+       0xa1,
+       E,
+       APOPW,
+       Ynone,
+       Ygs,
+       0,
+       Pe,
+       0x0f,
+       0xa9,
+       E,
+
+       /* mov seg */
+       AMOVW,
+       Yes,
+       Yml,
+       1,
+       0x8c,
+       0,
+       0,
+       0,
+       AMOVW,
+       Ycs,
+       Yml,
+       1,
+       0x8c,
+       1,
+       0,
+       0,
+       AMOVW,
+       Yss,
+       Yml,
+       1,
+       0x8c,
+       2,
+       0,
+       0,
+       AMOVW,
+       Yds,
+       Yml,
+       1,
+       0x8c,
+       3,
+       0,
+       0,
+       AMOVW,
+       Yfs,
+       Yml,
+       1,
+       0x8c,
+       4,
+       0,
+       0,
+       AMOVW,
+       Ygs,
+       Yml,
+       1,
+       0x8c,
+       5,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Yes,
+       2,
+       0x8e,
+       0,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Ycs,
+       2,
+       0x8e,
+       1,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Yss,
+       2,
+       0x8e,
+       2,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Yds,
+       2,
+       0x8e,
+       3,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Yfs,
+       2,
+       0x8e,
+       4,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Ygs,
+       2,
+       0x8e,
+       5,
+       0,
+       0,
+
+       /* mov cr */
+       AMOVL,
+       Ycr0,
+       Yml,
+       3,
+       0x0f,
+       0x20,
+       0,
+       0,
+       AMOVL,
+       Ycr2,
+       Yml,
+       3,
+       0x0f,
+       0x20,
+       2,
+       0,
+       AMOVL,
+       Ycr3,
+       Yml,
+       3,
+       0x0f,
+       0x20,
+       3,
+       0,
+       AMOVL,
+       Ycr4,
+       Yml,
+       3,
+       0x0f,
+       0x20,
+       4,
+       0,
+       AMOVL,
+       Yml,
+       Ycr0,
+       4,
+       0x0f,
+       0x22,
+       0,
+       0,
+       AMOVL,
+       Yml,
+       Ycr2,
+       4,
+       0x0f,
+       0x22,
+       2,
+       0,
+       AMOVL,
+       Yml,
+       Ycr3,
+       4,
+       0x0f,
+       0x22,
+       3,
+       0,
+       AMOVL,
+       Yml,
+       Ycr4,
+       4,
+       0x0f,
+       0x22,
+       4,
+       0,
+
+       /* mov dr */
+       AMOVL,
+       Ydr0,
+       Yml,
+       3,
+       0x0f,
+       0x21,
+       0,
+       0,
+       AMOVL,
+       Ydr6,
+       Yml,
+       3,
+       0x0f,
+       0x21,
+       6,
+       0,
+       AMOVL,
+       Ydr7,
+       Yml,
+       3,
+       0x0f,
+       0x21,
+       7,
+       0,
+       AMOVL,
+       Yml,
+       Ydr0,
+       4,
+       0x0f,
+       0x23,
+       0,
+       0,
+       AMOVL,
+       Yml,
+       Ydr6,
+       4,
+       0x0f,
+       0x23,
+       6,
+       0,
+       AMOVL,
+       Yml,
+       Ydr7,
+       4,
+       0x0f,
+       0x23,
+       7,
+       0,
+
+       /* mov tr */
+       AMOVL,
+       Ytr6,
+       Yml,
+       3,
+       0x0f,
+       0x24,
+       6,
+       0,
+       AMOVL,
+       Ytr7,
+       Yml,
+       3,
+       0x0f,
+       0x24,
+       7,
+       0,
+       AMOVL,
+       Yml,
+       Ytr6,
+       4,
+       0x0f,
+       0x26,
+       6,
+       E,
+       AMOVL,
+       Yml,
+       Ytr7,
+       4,
+       0x0f,
+       0x26,
+       7,
+       E,
+
+       /* lgdt, sgdt, lidt, sidt */
+       AMOVL,
+       Ym,
+       Ygdtr,
+       4,
+       0x0f,
+       0x01,
+       2,
+       0,
+       AMOVL,
+       Ygdtr,
+       Ym,
+       3,
+       0x0f,
+       0x01,
+       0,
+       0,
+       AMOVL,
+       Ym,
+       Yidtr,
+       4,
+       0x0f,
+       0x01,
+       3,
+       0,
+       AMOVL,
+       Yidtr,
+       Ym,
+       3,
+       0x0f,
+       0x01,
+       1,
+       0,
+
+       /* lldt, sldt */
+       AMOVW,
+       Yml,
+       Yldtr,
+       4,
+       0x0f,
+       0x00,
+       2,
+       0,
+       AMOVW,
+       Yldtr,
+       Yml,
+       3,
+       0x0f,
+       0x00,
+       0,
+       0,
+
+       /* lmsw, smsw */
+       AMOVW,
+       Yml,
+       Ymsw,
+       4,
+       0x0f,
+       0x01,
+       6,
+       0,
+       AMOVW,
+       Ymsw,
+       Yml,
+       3,
+       0x0f,
+       0x01,
+       4,
+       0,
+
+       /* ltr, str */
+       AMOVW,
+       Yml,
+       Ytask,
+       4,
+       0x0f,
+       0x00,
+       3,
+       0,
+       AMOVW,
+       Ytask,
+       Yml,
+       3,
+       0x0f,
+       0x00,
+       1,
+       0,
+
+       /* load full pointer */
+       AMOVL,
+       Yml,
+       Ycol,
+       5,
+       0,
+       0,
+       0,
+       0,
+       AMOVW,
+       Yml,
+       Ycol,
+       5,
+       Pe,
+       0,
+       0,
+       0,
+
+       /* double shift */
+       ASHLL,
+       Ycol,
+       Yml,
+       6,
+       0xa4,
+       0xa5,
+       0,
+       0,
+       ASHRL,
+       Ycol,
+       Yml,
+       6,
+       0xac,
+       0xad,
+       0,
+       0,
+
+       /* extra imul */
+       AIMULW,
+       Yml,
+       Yrl,
+       7,
+       Pq,
+       0xaf,
+       0,
+       0,
+       AIMULL,
+       Yml,
+       Yrl,
+       7,
+       Pm,
+       0xaf,
+       0,
+       0,
+
+       /* load TLS base pointer */
+       AMOVL,
+       Ytls,
+       Yrl,
+       8,
+       0,
+       0,
+       0,
+       0,
+       0,
+}
+
+// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
+// which is not referenced in a->type.
+// If a is empty, it returns BX to account for MULB-like instructions
+// that might use DX and AX.
+func byteswapreg(ctxt *obj.Link, a *obj.Addr) int {
+
+       var cana int
+       var canb int
+       var canc int
+       var cand int
+
+       cand = 1
+       canc = cand
+       canb = canc
+       cana = canb
+
+       switch a.Type {
+       case D_NONE:
+               cand = 0
+               cana = cand
+
+       case D_AX,
+               D_AL,
+               D_AH,
+               D_INDIR + D_AX:
+               cana = 0
+
+       case D_BX,
+               D_BL,
+               D_BH,
+               D_INDIR + D_BX:
+               canb = 0
+
+       case D_CX,
+               D_CL,
+               D_CH,
+               D_INDIR + D_CX:
+               canc = 0
+
+       case D_DX,
+               D_DL,
+               D_DH,
+               D_INDIR + D_DX:
+               cand = 0
+               break
+       }
+
+       switch a.Index {
+       case D_AX:
+               cana = 0
+
+       case D_BX:
+               canb = 0
+
+       case D_CX:
+               canc = 0
+
+       case D_DX:
+               cand = 0
+               break
+       }
+
+       if cana != 0 {
+               return D_AX
+       }
+       if canb != 0 {
+               return D_BX
+       }
+       if canc != 0 {
+               return D_CX
+       }
+       if cand != 0 {
+               return D_DX
+       }
+
+       ctxt.Diag("impossible byte register")
+       log.Fatalf("bad code")
+       return 0
+}
+
+func subreg(p *obj.Prog, from int, to int) {
+       if false { /* debug['Q'] */
+               fmt.Printf("\n%v\ts/%v/%v/\n", p, Rconv(from), Rconv(to))
+       }
+
+       if int(p.From.Type) == from {
+               p.From.Type = int16(to)
+               p.Ft = 0
+       }
+
+       if int(p.To.Type) == from {
+               p.To.Type = int16(to)
+               p.Tt = 0
+       }
+
+       if int(p.From.Index) == from {
+               p.From.Index = uint8(to)
+               p.Ft = 0
+       }
+
+       if int(p.To.Index) == from {
+               p.To.Index = uint8(to)
+               p.Tt = 0
+       }
+
+       from += D_INDIR
+       if int(p.From.Type) == from {
+               p.From.Type = int16(to + D_INDIR)
+               p.Ft = 0
+       }
+
+       if int(p.To.Type) == from {
+               p.To.Type = int16(to + D_INDIR)
+               p.Tt = 0
+       }
+
+       if false { /* debug['Q'] */
+               fmt.Printf("%v\n", p)
+       }
+}
+
+func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
+       switch op {
+       case Pm,
+               Pe,
+               Pf2,
+               Pf3:
+               if osize != 1 {
+                       if op != Pm {
+                               ctxt.Andptr[0] = byte(op)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = Pm
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       z++
+                       op = int(o.op[z])
+                       break
+               }
+               fallthrough
+
+       default:
+               if -cap(ctxt.Andptr) == -cap(ctxt.And) || ctxt.And[-cap(ctxt.Andptr)+cap(ctxt.And[:])-1] != Pm {
+                       ctxt.Andptr[0] = Pm
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               break
+       }
+
+       ctxt.Andptr[0] = byte(op)
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return z
+}
+
+func doasm(ctxt *obj.Link, p *obj.Prog) {
+       var o *Optab
+       var q *obj.Prog
+       var pp obj.Prog
+       var t []byte
+       var z int
+       var op int
+       var ft int
+       var tt int
+       var breg int
+       var v int32
+       var pre int32
+       var rel obj.Reloc
+       var r *obj.Reloc
+       var a *obj.Addr
+
+       ctxt.Curp = p // TODO
+
+       pre = int32(prefixof(ctxt, &p.From))
+
+       if pre != 0 {
+               ctxt.Andptr[0] = byte(pre)
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+       pre = int32(prefixof(ctxt, &p.To))
+       if pre != 0 {
+               ctxt.Andptr[0] = byte(pre)
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+
+       if p.Ft == 0 {
+               p.Ft = uint8(oclass(&p.From))
+       }
+       if p.Tt == 0 {
+               p.Tt = uint8(oclass(&p.To))
+       }
+
+       ft = int(p.Ft) * Ymax
+       tt = int(p.Tt) * Ymax
+       o = &optab[p.As]
+       t = o.ytab
+       if t == nil {
+               ctxt.Diag("asmins: noproto %v", p)
+               return
+       }
+
+       for z = 0; t[0] != 0; (func() { z += int(t[3]); t = t[4:] })() {
+               if ycover[ft+int(t[0])] != 0 {
+                       if ycover[tt+int(t[1])] != 0 {
+                               goto found
+                       }
+               }
+       }
+       goto domov
+
+found:
+       switch o.prefix {
+       case Pq: /* 16 bit escape and opcode escape */
+               ctxt.Andptr[0] = Pe
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pf2, /* xmm opcode escape */
+               Pf3:
+               ctxt.Andptr[0] = byte(o.prefix)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pm: /* opcode escape */
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pe: /* 16 bit escape */
+               ctxt.Andptr[0] = Pe
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pb: /* botch */
+               break
+       }
+
+       op = int(o.op[z])
+       switch t[2] {
+       default:
+               ctxt.Diag("asmins: unknown z %d %v", t[2], p)
+               return
+
+       case Zpseudo:
+               break
+
+       case Zlit:
+               for ; ; z++ {
+                       op = int(o.op[z])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case Zlitm_r:
+               for ; ; z++ {
+                       op = int(o.op[z])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+       case Zm_r:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+       case Zm2_r:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(o.op[z+1])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+       case Zm_r_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+       case Zm_r_i_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+               ctxt.Andptr[0] = byte(p.To.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zibm_r:
+               for {
+                       tmp2 := z
+                       z++
+                       op = int(o.op[tmp2])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+               ctxt.Andptr[0] = byte(p.To.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zaut_r:
+               ctxt.Andptr[0] = 0x8d
+               ctxt.Andptr = ctxt.Andptr[1:] /* leal */
+               if p.From.Type != D_ADDR {
+                       ctxt.Diag("asmins: Zaut sb type ADDR")
+               }
+               p.From.Type = int16(p.From.Index)
+               p.From.Index = D_NONE
+               p.Ft = 0
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+               p.From.Index = uint8(p.From.Type)
+               p.From.Type = D_ADDR
+               p.Ft = 0
+
+       case Zm_o:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, int(o.op[z+1]))
+
+       case Zr_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, reg[p.From.Type])
+
+       case Zr_m_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.To, reg[p.From.Type])
+
+       case Zr_m_i_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.To, reg[p.From.Type])
+               ctxt.Andptr[0] = byte(p.From.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zcallindreg:
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc)
+               r.Type = obj.R_CALLIND
+               r.Siz = 0
+               fallthrough
+
+               // fallthrough
+       case Zo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmand(ctxt, p, &p.To, int(o.op[z+1]))
+
+       case Zm_ibo:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, int(o.op[z+1]))
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.To, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zibo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, int(o.op[z+1]))
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Z_ib,
+               Zib_:
+               if t[2] == Zib_ {
+                       a = &p.From
+               } else {
+
+                       a = &p.To
+               }
+               v = vaddr(ctxt, p, a, nil)
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(v)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zib_rp:
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zil_rp:
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, &p.From, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, &p.From)
+               }
+
+       case Zib_rr:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, reg[p.To.Type])
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Z_il,
+               Zil_:
+               if t[2] == Zil_ {
+                       a = &p.From
+               } else {
+
+                       a = &p.To
+               }
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, a, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, a)
+               }
+
+       case Zm_ilo,
+               Zilo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if t[2] == Zilo_m {
+                       a = &p.From
+                       asmand(ctxt, p, &p.To, int(o.op[z+1]))
+               } else {
+
+                       a = &p.To
+                       asmand(ctxt, p, &p.From, int(o.op[z+1]))
+               }
+
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, a, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, a)
+               }
+
+       case Zil_rr:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, reg[p.To.Type])
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, &p.From, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, &p.From)
+               }
+
+       case Z_rp:
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zrp_:
+               ctxt.Andptr[0] = byte(op + reg[p.From.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zclr:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, reg[p.To.Type])
+
+       case Zcall:
+               if p.To.Sym == nil {
+                       ctxt.Diag("call without target")
+                       log.Fatalf("bad code")
+               }
+
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               r.Type = obj.R_CALL
+               r.Siz = 4
+               r.Sym = p.To.Sym
+               r.Add = p.To.Offset
+               put4(ctxt, 0)
+
+       case Zbr,
+               Zjmp,
+               Zloop:
+               if p.To.Sym != nil {
+                       if t[2] != Zjmp {
+                               ctxt.Diag("branch to ATEXT")
+                               log.Fatalf("bad code")
+                       }
+
+                       ctxt.Andptr[0] = byte(o.op[z+1])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       r = obj.Addrel(ctxt.Cursym)
+                       r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+                       r.Sym = p.To.Sym
+                       r.Type = obj.R_PCREL
+                       r.Siz = 4
+                       put4(ctxt, 0)
+                       break
+               }
+
+               // Assumes q is in this function.
+               // Fill in backward jump now.
+               q = p.Pcond
+
+               if q == nil {
+                       ctxt.Diag("jmp/branch/loop without target")
+                       log.Fatalf("bad code")
+               }
+
+               if p.Back&1 != 0 {
+                       v = int32(q.Pc - (p.Pc + 2))
+                       if v >= -128 {
+                               if p.As == AJCXZW {
+                                       ctxt.Andptr[0] = 0x67
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                               }
+                               ctxt.Andptr[0] = byte(op)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       } else if t[2] == Zloop {
+                               ctxt.Diag("loop too far: %v", p)
+                       } else {
+
+                               v -= 5 - 2
+                               if t[2] == Zbr {
+                                       ctxt.Andptr[0] = 0x0f
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                                       v--
+                               }
+
+                               ctxt.Andptr[0] = byte(o.op[z+1])
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 8)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 16)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 24)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+
+                       break
+               }
+
+               // Annotate target; will fill in later.
+               p.Forwd = q.Comefrom
+
+               q.Comefrom = p
+               if p.Back&2 != 0 { // short
+                       if p.As == AJCXZW {
+                               ctxt.Andptr[0] = 0x67
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else if t[2] == Zloop {
+                       ctxt.Diag("loop too far: %v", p)
+               } else {
+
+                       if t[2] == Zbr {
+                               ctxt.Andptr[0] = 0x0f
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = byte(o.op[z+1])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case Zcallcon,
+               Zjmpcon:
+               if t[2] == Zcallcon {
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       ctxt.Andptr[0] = byte(o.op[z+1])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               r.Type = obj.R_PCREL
+               r.Siz = 4
+               r.Add = p.To.Offset
+               put4(ctxt, 0)
+
+       case Zcallind:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(o.op[z+1])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               r.Type = obj.R_ADDR
+               r.Siz = 4
+               r.Add = p.To.Offset
+               r.Sym = p.To.Sym
+               put4(ctxt, 0)
+
+       case Zbyte:
+               v = vaddr(ctxt, p, &p.From, &rel)
+               if rel.Siz != 0 {
+                       rel.Siz = uint8(op)
+                       r = obj.Addrel(ctxt.Cursym)
+                       *r = rel
+                       r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               }
+
+               ctxt.Andptr[0] = byte(v)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if op > 1 {
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       if op > 2 {
+                               ctxt.Andptr[0] = byte(v >> 16)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 24)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+               }
+
+       case Zmov:
+               goto domov
+       }
+
+       return
+
+domov:
+       for t = []byte(ymovtab); t[0] != 0; t = t[8:] {
+               if p.As == int16(t[0]) {
+                       if ycover[ft+int(t[1])] != 0 {
+                               if ycover[tt+int(t[2])] != 0 {
+                                       goto mfound
+                               }
+                       }
+               }
+       }
+
+       /*
+        * here, the assembly has failed.
+        * if its a byte instruction that has
+        * unaddressable registers, try to
+        * exchange registers and reissue the
+        * instruction with the operands renamed.
+        */
+bad:
+       pp = *p
+
+       z = int(p.From.Type)
+       if z >= D_BP && z <= D_DI {
+               breg = byteswapreg(ctxt, &p.To)
+               if breg != D_AX {
+                       ctxt.Andptr[0] = 0x87
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+                       asmand(ctxt, p, &p.From, reg[breg])
+                       subreg(&pp, z, breg)
+                       doasm(ctxt, &pp)
+                       ctxt.Andptr[0] = 0x87
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+                       asmand(ctxt, p, &p.From, reg[breg])
+               } else {
+
+                       ctxt.Andptr[0] = byte(0x90 + reg[z])
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+                       subreg(&pp, z, D_AX)
+                       doasm(ctxt, &pp)
+                       ctxt.Andptr[0] = byte(0x90 + reg[z])
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+               }
+
+               return
+       }
+
+       z = int(p.To.Type)
+       if z >= D_BP && z <= D_DI {
+               breg = byteswapreg(ctxt, &p.From)
+               if breg != D_AX {
+                       ctxt.Andptr[0] = 0x87
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+                       asmand(ctxt, p, &p.To, reg[breg])
+                       subreg(&pp, z, breg)
+                       doasm(ctxt, &pp)
+                       ctxt.Andptr[0] = 0x87
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+                       asmand(ctxt, p, &p.To, reg[breg])
+               } else {
+
+                       ctxt.Andptr[0] = byte(0x90 + reg[z])
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+                       subreg(&pp, z, D_AX)
+                       doasm(ctxt, &pp)
+                       ctxt.Andptr[0] = byte(0x90 + reg[z])
+                       ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+               }
+
+               return
+       }
+
+       ctxt.Diag("doasm: notfound t2=%x from=%x to=%x %v", t[2], uint16(p.From.Type), uint16(p.To.Type), p)
+       return
+
+mfound:
+       switch t[3] {
+       default:
+               ctxt.Diag("asmins: unknown mov %d %v", t[3], p)
+
+       case 0: /* lit */
+               for z = 4; t[z] != E; z++ {
+
+                       ctxt.Andptr[0] = t[z]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case 1: /* r,m */
+               ctxt.Andptr[0] = t[4]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmand(ctxt, p, &p.To, int(t[5]))
+
+       case 2: /* m,r */
+               ctxt.Andptr[0] = t[4]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmand(ctxt, p, &p.From, int(t[5]))
+
+       case 3: /* r,m - 2op */
+               ctxt.Andptr[0] = t[4]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = t[5]
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, int(t[6]))
+
+       case 4: /* m,r - 2op */
+               ctxt.Andptr[0] = t[4]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = t[5]
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, int(t[6]))
+
+       case 5: /* load full pointer, trash heap */
+               if t[4] != 0 {
+
+                       ctxt.Andptr[0] = t[4]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               switch p.To.Index {
+               default:
+                       goto bad
+
+               case D_DS:
+                       ctxt.Andptr[0] = 0xc5
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_SS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb2
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_ES:
+                       ctxt.Andptr[0] = 0xc4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_FS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_GS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb5
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       break
+               }
+
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+       case 6: /* double shift */
+               z = int(p.From.Type)
+
+               switch z {
+               default:
+                       goto bad
+
+               case D_CONST:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = t[4]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &p.To, reg[p.From.Index])
+                       ctxt.Andptr[0] = byte(p.From.Offset)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_CL,
+                       D_CX:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = t[5]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &p.To, reg[p.From.Index])
+                       break
+               }
+
+       case 7: /* imul rm,r */
+               if t[4] == Pq {
+
+                       ctxt.Andptr[0] = Pe
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = Pm
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       ctxt.Andptr[0] = t[4]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               ctxt.Andptr[0] = t[5]
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+               // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
+       // where you load the TLS base register into a register and then index off that
+       // register to access the actual TLS variables. Systems that allow direct TLS access
+       // are handled in prefixof above and should not be listed here.
+       case 8: /* mov tls, r */
+               switch ctxt.Headtype {
+
+               default:
+                       log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype))
+
+                       // ELF TLS base is 0(GS).
+               case obj.Hlinux,
+                       obj.Hnacl:
+                       pp.From = p.From
+
+                       pp.From.Type = D_INDIR + D_GS
+                       pp.From.Offset = 0
+                       pp.From.Index = D_NONE
+                       pp.From.Scale = 0
+                       ctxt.Andptr[0] = 0x65
+                       ctxt.Andptr = ctxt.Andptr[1:] // GS
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, reg[p.To.Type])
+
+               case obj.Hplan9:
+                       if ctxt.Plan9privates == nil {
+                               ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+                       }
+                       pp.From = obj.Addr{}
+                       pp.From.Type = D_EXTERN
+                       pp.From.Sym = ctxt.Plan9privates
+                       pp.From.Offset = 0
+                       pp.From.Index = D_NONE
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, reg[p.To.Type])
+
+                       // Windows TLS base is always 0x14(FS).
+               case obj.Hwindows:
+                       pp.From = p.From
+
+                       pp.From.Type = D_INDIR + D_FS
+                       pp.From.Offset = 0x14
+                       pp.From.Index = D_NONE
+                       pp.From.Scale = 0
+                       ctxt.Andptr[0] = 0x64
+                       ctxt.Andptr = ctxt.Andptr[1:] // FS
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, reg[p.To.Type])
+                       break
+               }
+
+               break
+       }
+}
+
+var naclret = []uint8{
+       0x5d, // POPL BP
+       // 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
+       0x83,
+       0xe5,
+       0xe0, // ANDL $~31, BP
+       0xff,
+       0xe5, // JMP BP
+}
+
+func asmins(ctxt *obj.Link, p *obj.Prog) {
+       var r *obj.Reloc
+
+       ctxt.Andptr = ctxt.And[:]
+
+       if p.As == AUSEFIELD {
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = 0
+               r.Sym = p.From.Sym
+               r.Type = obj.R_USEFIELD
+               r.Siz = 0
+               return
+       }
+
+       if ctxt.Headtype == obj.Hnacl {
+               switch p.As {
+               case ARET:
+                       copy(ctxt.Andptr, naclret)
+                       ctxt.Andptr = ctxt.Andptr[len(naclret):]
+                       return
+
+               case ACALL,
+                       AJMP:
+                       if D_AX <= p.To.Type && p.To.Type <= D_DI {
+                               ctxt.Andptr[0] = 0x83
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_AX))
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = 0xe0
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+
+               case AINT:
+                       ctxt.Andptr[0] = 0xf4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+       }
+
+       doasm(ctxt, p)
+       if -cap(ctxt.Andptr) > -cap(ctxt.And[len(ctxt.And):]) {
+               fmt.Printf("and[] is too short - %d byte instruction\n", -cap(ctxt.Andptr)+cap(ctxt.And[:]))
+               log.Fatalf("bad code")
+       }
+}
diff --git a/src/cmd/internal/obj/i386/list8.go b/src/cmd/internal/obj/i386/list8.go
new file mode 100644 (file)
index 0000000..5a55890
--- /dev/null
@@ -0,0 +1,273 @@
+// Inferno utils/8c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.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.
+
+package i386
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+)
+
+const (
+       STRINGSZ = 1000
+)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+       var str string
+       var fp string
+
+       switch p.As {
+       case ADATA:
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, 0, &p.To))
+
+       case ATEXT:
+               if p.From.Scale != 0 {
+                       str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, fmtLong, &p.To))
+                       break
+               }
+
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+
+       default:
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+               break
+       }
+
+       fp += str
+       return fp
+}
+
+func Aconv(i int) string {
+       var fp string
+
+       fp += Anames[i]
+       return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+       var str string
+       var s string
+       var fp string
+
+       var i int
+
+       i = int(a.Type)
+
+       if flag&fmtLong != 0 /*untyped*/ {
+               if i == D_CONST2 {
+                       str = fmt.Sprintf("$%d-%d", a.Offset, a.Offset2)
+               } else {
+
+                       // ATEXT dst is not constant
+                       str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+               }
+
+               goto brk
+       }
+
+       if i >= D_INDIR {
+               if a.Offset != 0 {
+                       str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(i-D_INDIR))
+               } else {
+
+                       str = fmt.Sprintf("(%v)", Rconv(i-D_INDIR))
+               }
+               goto brk
+       }
+
+       switch i {
+       default:
+               if a.Offset != 0 {
+                       str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(i))
+               } else {
+
+                       str = fmt.Sprintf("%v", Rconv(i))
+               }
+
+       case D_NONE:
+               str = ""
+
+       case D_BRANCH:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+               } else if p != nil && p.Pcond != nil {
+                       str = fmt.Sprintf("%d", p.Pcond.Pc)
+               } else if a.U.Branch != nil {
+                       str = fmt.Sprintf("%d", a.U.Branch.Pc)
+               } else {
+
+                       str = fmt.Sprintf("%d(PC)", a.Offset)
+               }
+
+       case D_EXTERN:
+               str = fmt.Sprintf("%s+%d(SB)", a.Sym.Name, a.Offset)
+
+       case D_STATIC:
+               str = fmt.Sprintf("%s<>+%d(SB)", a.Sym.Name, a.Offset)
+
+       case D_AUTO:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s+%d(SP)", a.Sym.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%d(SP)", a.Offset)
+               }
+
+       case D_PARAM:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s+%d(FP)", a.Sym.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%d(FP)", a.Offset)
+               }
+
+       case D_CONST:
+               str = fmt.Sprintf("$%d", a.Offset)
+
+       case D_CONST2:
+               if !(flag&fmtLong != 0 /*untyped*/) {
+                       // D_CONST2 outside of ATEXT should not happen
+                       str = fmt.Sprintf("!!$%d-%d", a.Offset, a.Offset2)
+               }
+
+       case D_FCONST:
+               str = fmt.Sprintf("$(%.17g)", a.U.Dval)
+
+       case D_SCONST:
+               str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+
+       case D_ADDR:
+               a.Type = int16(a.Index)
+               a.Index = D_NONE
+               str = fmt.Sprintf("$%v", Dconv(p, 0, a))
+               a.Index = uint8(a.Type)
+               a.Type = D_ADDR
+               goto conv
+       }
+
+brk:
+       if a.Index != D_NONE {
+               s = fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
+               str += s
+       }
+
+conv:
+       fp += str
+       return fp
+}
+
+var Register = []string{
+       "AL", /* [D_AL] */
+       "CL",
+       "DL",
+       "BL",
+       "AH",
+       "CH",
+       "DH",
+       "BH",
+       "AX", /* [D_AX] */
+       "CX",
+       "DX",
+       "BX",
+       "SP",
+       "BP",
+       "SI",
+       "DI",
+       "F0", /* [D_F0] */
+       "F1",
+       "F2",
+       "F3",
+       "F4",
+       "F5",
+       "F6",
+       "F7",
+       "CS", /* [D_CS] */
+       "SS",
+       "DS",
+       "ES",
+       "FS",
+       "GS",
+       "GDTR", /* [D_GDTR] */
+       "IDTR", /* [D_IDTR] */
+       "LDTR", /* [D_LDTR] */
+       "MSW",  /* [D_MSW] */
+       "TASK", /* [D_TASK] */
+       "CR0",  /* [D_CR] */
+       "CR1",
+       "CR2",
+       "CR3",
+       "CR4",
+       "CR5",
+       "CR6",
+       "CR7",
+       "DR0", /* [D_DR] */
+       "DR1",
+       "DR2",
+       "DR3",
+       "DR4",
+       "DR5",
+       "DR6",
+       "DR7",
+       "TR0", /* [D_TR] */
+       "TR1",
+       "TR2",
+       "TR3",
+       "TR4",
+       "TR5",
+       "TR6",
+       "TR7",
+       "X0", /* [D_X0] */
+       "X1",
+       "X2",
+       "X3",
+       "X4",
+       "X5",
+       "X6",
+       "X7",
+       "TLS",  /* [D_TLS] */
+       "NONE", /* [D_NONE] */
+}
+
+func Rconv(r int) string {
+       var str string
+       var fp string
+
+       if r >= D_AL && r <= D_NONE {
+               str = fmt.Sprintf("%s", Register[r-D_AL])
+       } else {
+
+               str = fmt.Sprintf("gok(%d)", r)
+       }
+
+       fp += str
+       return fp
+}
diff --git a/src/cmd/internal/obj/i386/obj8.go b/src/cmd/internal/obj/i386/obj8.go
new file mode 100644 (file)
index 0000000..909e8f5
--- /dev/null
@@ -0,0 +1,996 @@
+// Inferno utils/8l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.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.
+
+package i386
+
+import (
+       "cmd/internal/obj"
+       "encoding/binary"
+       "fmt"
+       "log"
+       "math"
+)
+
+var zprg = obj.Prog{
+       Back: 2,
+       As:   AGOK,
+       From: obj.Addr{
+               Type:  D_NONE,
+               Index: D_NONE,
+               Scale: 1,
+       },
+       To: obj.Addr{
+               Type:  D_NONE,
+               Index: D_NONE,
+               Scale: 1,
+       },
+}
+
+func symtype(a *obj.Addr) int {
+       var t int
+
+       t = int(a.Type)
+       if t == D_ADDR {
+               t = int(a.Index)
+       }
+       return t
+}
+
+func isdata(p *obj.Prog) bool {
+       return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+       return p.As == ACALL
+}
+
+func datasize(p *obj.Prog) int {
+       return int(p.From.Scale)
+}
+
+func textflag(p *obj.Prog) int {
+       return int(p.From.Scale)
+}
+
+func settextflag(p *obj.Prog, f int) {
+       p.From.Scale = int8(f)
+}
+
+func canuselocaltls(ctxt *obj.Link) int {
+       switch ctxt.Headtype {
+       case obj.Hlinux,
+               obj.Hnacl,
+               obj.Hplan9,
+               obj.Hwindows:
+               return 0
+       }
+
+       return 1
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+       var literal string
+       var s *obj.LSym
+       var q *obj.Prog
+
+       // See obj6.c for discussion of TLS.
+       if canuselocaltls(ctxt) != 0 {
+
+               // Reduce TLS initial exec model to TLS local exec model.
+               // Sequences like
+               //      MOVL TLS, BX
+               //      ... off(BX)(TLS*1) ...
+               // become
+               //      NOP
+               //      ... off(TLS) ...
+               if p.As == AMOVL && p.From.Type == D_TLS && D_AX <= p.To.Type && p.To.Type <= D_DI {
+
+                       p.As = ANOP
+                       p.From.Type = D_NONE
+                       p.To.Type = D_NONE
+               }
+
+               if p.From.Index == D_TLS && D_INDIR+D_AX <= p.From.Type && p.From.Type <= D_INDIR+D_DI {
+                       p.From.Type = D_INDIR + D_TLS
+                       p.From.Scale = 0
+                       p.From.Index = D_NONE
+               }
+
+               if p.To.Index == D_TLS && D_INDIR+D_AX <= p.To.Type && p.To.Type <= D_INDIR+D_DI {
+                       p.To.Type = D_INDIR + D_TLS
+                       p.To.Scale = 0
+                       p.To.Index = D_NONE
+               }
+       } else {
+
+               // As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
+               // The instruction
+               //      MOVL off(TLS), BX
+               // becomes the sequence
+               //      MOVL TLS, BX
+               //      MOVL off(BX)(TLS*1), BX
+               // This allows the C compilers to emit references to m and g using the direct off(TLS) form.
+               if p.As == AMOVL && p.From.Type == D_INDIR+D_TLS && D_AX <= p.To.Type && p.To.Type <= D_DI {
+
+                       q = obj.Appendp(ctxt, p)
+                       q.As = p.As
+                       q.From = p.From
+                       q.From.Type = D_INDIR + p.To.Type
+                       q.From.Index = D_TLS
+                       q.From.Scale = 2 // TODO: use 1
+                       q.To = p.To
+                       p.From.Type = D_TLS
+                       p.From.Index = D_NONE
+                       p.From.Offset = 0
+               }
+       }
+
+       // TODO: Remove.
+       if ctxt.Headtype == obj.Hplan9 {
+
+               if p.From.Scale == 1 && p.From.Index == D_TLS {
+                       p.From.Scale = 2
+               }
+               if p.To.Scale == 1 && p.To.Index == D_TLS {
+                       p.To.Scale = 2
+               }
+       }
+
+       // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+       switch p.As {
+
+       case ACALL,
+               AJMP,
+               ARET:
+               if (p.To.Type == D_EXTERN || p.To.Type == D_STATIC) && p.To.Sym != nil {
+                       p.To.Type = D_BRANCH
+               }
+               break
+       }
+
+       // Rewrite float constants to values stored in memory.
+       switch p.As {
+
+       // Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
+       case AMOVSS:
+               if p.From.Type == D_FCONST {
+
+                       if p.From.U.Dval == 0 {
+                               if p.To.Type >= D_X0 {
+                                       if p.To.Type <= D_X7 {
+                                               p.As = AXORPS
+                                               p.From.Type = p.To.Type
+                                               p.From.Index = p.To.Index
+                                               break
+                                       }
+                               }
+                       }
+               }
+               fallthrough
+
+               // fallthrough
+
+       case AFMOVF,
+               AFADDF,
+               AFSUBF,
+               AFSUBRF,
+               AFMULF,
+               AFDIVF,
+               AFDIVRF,
+               AFCOMF,
+               AFCOMFP,
+               AADDSS,
+               ASUBSS,
+               AMULSS,
+               ADIVSS,
+               ACOMISS,
+               AUCOMISS:
+               if p.From.Type == D_FCONST {
+
+                       var i32 uint32
+                       var f32 float32
+                       f32 = float32(p.From.U.Dval)
+                       i32 = math.Float32bits(f32)
+                       literal = fmt.Sprintf("$f32.%08x", i32)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint32(ctxt, s, i32)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_EXTERN
+                       p.From.Sym = s
+                       p.From.Offset = 0
+               }
+
+               // Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
+       case AMOVSD:
+               if p.From.Type == D_FCONST {
+
+                       if p.From.U.Dval == 0 {
+                               if p.To.Type >= D_X0 {
+                                       if p.To.Type <= D_X7 {
+                                               p.As = AXORPS
+                                               p.From.Type = p.To.Type
+                                               p.From.Index = p.To.Index
+                                               break
+                                       }
+                               }
+                       }
+               }
+               fallthrough
+
+               // fallthrough
+
+       case AFMOVD,
+               AFADDD,
+               AFSUBD,
+               AFSUBRD,
+               AFMULD,
+               AFDIVD,
+               AFDIVRD,
+               AFCOMD,
+               AFCOMDP,
+               AADDSD,
+               ASUBSD,
+               AMULSD,
+               ADIVSD,
+               ACOMISD,
+               AUCOMISD:
+               if p.From.Type == D_FCONST {
+
+                       var i64 uint64
+                       i64 = math.Float64bits(p.From.U.Dval)
+                       literal = fmt.Sprintf("$f64.%016x", i64)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint64(ctxt, s, i64)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_EXTERN
+                       p.From.Sym = s
+                       p.From.Offset = 0
+               }
+
+               break
+       }
+}
+
+func prg() *obj.Prog {
+       p := zprg
+       return &p
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var p1 *obj.Prog
+       var p2 *obj.Prog
+       var autoffset int32
+       var deltasp int32
+       var a int
+
+       if ctxt.Symmorestack[0] == nil {
+               ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+               ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+       }
+
+       if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
+               ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+       }
+
+       ctxt.Cursym = cursym
+
+       if cursym.Text == nil || cursym.Text.Link == nil {
+               return
+       }
+
+       p = cursym.Text
+       autoffset = int32(p.To.Offset)
+       if autoffset < 0 {
+               autoffset = 0
+       }
+
+       cursym.Locals = autoffset
+       cursym.Args = p.To.Offset2
+
+       q = nil
+
+       if !(p.From.Scale&obj.NOSPLIT != 0) || (p.From.Scale&obj.WRAPPER != 0) {
+               p = obj.Appendp(ctxt, p)
+               p = load_g_cx(ctxt, p) // load g into CX
+       }
+
+       if !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+               p = stacksplit(ctxt, p, autoffset, bool2int(!(cursym.Text.From.Scale&obj.NEEDCTXT != 0)), &q) // emit split check
+       }
+
+       if autoffset != 0 {
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AADJSP
+               p.From.Type = D_CONST
+               p.From.Offset = int64(autoffset)
+               p.Spadj = autoffset
+       } else {
+
+               // zero-byte stack adjustment.
+               // Insert a fake non-zero adjustment so that stkcheck can
+               // recognize the end of the stack-splitting prolog.
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ANOP
+               p.Spadj = int32(-ctxt.Arch.Ptrsize)
+               p = obj.Appendp(ctxt, p)
+               p.As = ANOP
+               p.Spadj = int32(ctxt.Arch.Ptrsize)
+       }
+
+       if q != nil {
+               q.Pcond = p
+       }
+       deltasp = autoffset
+
+       if cursym.Text.From.Scale&obj.WRAPPER != 0 {
+               // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+               //
+               //      MOVL g_panic(CX), BX
+               //      TESTL BX, BX
+               //      JEQ end
+               //      LEAL (autoffset+4)(SP), DI
+               //      CMPL panic_argp(BX), DI
+               //      JNE end
+               //      MOVL SP, panic_argp(BX)
+               // end:
+               //      NOP
+               //
+               // The NOP is needed to give the jumps somewhere to land.
+               // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
+
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVL
+               p.From.Type = D_INDIR + D_CX
+               p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+               p.To.Type = D_BX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ATESTL
+               p.From.Type = D_BX
+               p.To.Type = D_BX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJEQ
+               p.To.Type = D_BRANCH
+               p1 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ALEAL
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = int64(autoffset) + 4
+               p.To.Type = D_DI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMPL
+               p.From.Type = D_INDIR + D_BX
+               p.From.Offset = 0 // Panic.argp
+               p.To.Type = D_DI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJNE
+               p.To.Type = D_BRANCH
+               p2 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVL
+               p.From.Type = D_SP
+               p.To.Type = D_INDIR + D_BX
+               p.To.Offset = 0 // Panic.argp
+
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ANOP
+               p1.Pcond = p
+               p2.Pcond = p
+       }
+
+       if ctxt.Debugzerostack != 0 && autoffset != 0 && !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+               // 8l -Z means zero the stack frame on entry.
+               // This slows down function calls but can help avoid
+               // false positives in garbage collection.
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVL
+               p.From.Type = D_SP
+               p.To.Type = D_DI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVL
+               p.From.Type = D_CONST
+               p.From.Offset = int64(autoffset) / 4
+               p.To.Type = D_CX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVL
+               p.From.Type = D_CONST
+               p.From.Offset = 0
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AREP
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ASTOSL
+       }
+
+       for ; p != nil; p = p.Link {
+               a = int(p.From.Type)
+               if a == D_AUTO {
+                       p.From.Offset += int64(deltasp)
+               }
+               if a == D_PARAM {
+                       p.From.Offset += int64(deltasp) + 4
+               }
+               a = int(p.To.Type)
+               if a == D_AUTO {
+                       p.To.Offset += int64(deltasp)
+               }
+               if a == D_PARAM {
+                       p.To.Offset += int64(deltasp) + 4
+               }
+
+               switch p.As {
+               default:
+                       continue
+
+               case APUSHL,
+                       APUSHFL:
+                       deltasp += 4
+                       p.Spadj = 4
+                       continue
+
+               case APUSHW,
+                       APUSHFW:
+                       deltasp += 2
+                       p.Spadj = 2
+                       continue
+
+               case APOPL,
+                       APOPFL:
+                       deltasp -= 4
+                       p.Spadj = -4
+                       continue
+
+               case APOPW,
+                       APOPFW:
+                       deltasp -= 2
+                       p.Spadj = -2
+                       continue
+
+               case ARET:
+                       break
+               }
+
+               if autoffset != deltasp {
+                       ctxt.Diag("unbalanced PUSH/POP")
+               }
+
+               if autoffset != 0 {
+                       p.As = AADJSP
+                       p.From.Type = D_CONST
+                       p.From.Offset = int64(-autoffset)
+                       p.Spadj = -autoffset
+                       p = obj.Appendp(ctxt, p)
+                       p.As = ARET
+
+                       // If there are instructions following
+                       // this ARET, they come from a branch
+                       // with the same stackframe, so undo
+                       // the cleanup.
+                       p.Spadj = +autoffset
+               }
+
+               if p.To.Sym != nil { // retjmp
+                       p.As = AJMP
+               }
+       }
+}
+
+// Append code to p to load g into cx.
+// Overwrites p with the first instruction (no first appendp).
+// Overwriting p is unusual but it lets use this in both the
+// prologue (caller must call appendp first) and in the epilogue.
+// Returns last new instruction.
+func load_g_cx(ctxt *obj.Link, p *obj.Prog) *obj.Prog {
+
+       var next *obj.Prog
+
+       p.As = AMOVL
+       p.From.Type = D_INDIR + D_TLS
+       p.From.Offset = 0
+       p.To.Type = D_CX
+
+       next = p.Link
+       progedit(ctxt, p)
+       for p.Link != next {
+               p = p.Link
+       }
+
+       if p.From.Index == D_TLS {
+               p.From.Scale = 2
+       }
+
+       return p
+}
+
+// Append code to p to check for stack split.
+// Appends to (does not overwrite) p.
+// Assumes g is in CX.
+// Returns last new instruction.
+// On return, *jmpok is the instruction that should jump
+// to the stack frame allocation if no split is needed.
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int, jmpok **obj.Prog) *obj.Prog {
+
+       var q *obj.Prog
+       var q1 *obj.Prog
+
+       if ctxt.Debugstack != 0 {
+               // 8l -K means check not only for stack
+               // overflow but stack underflow.
+               // On underflow, INT 3 (breakpoint).
+               // Underflow itself is rare but this also
+               // catches out-of-sync stack guard info.
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ACMPL
+               p.From.Type = D_INDIR + D_CX
+               p.From.Offset = 4
+               p.To.Type = D_SP
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJCC
+               p.To.Type = D_BRANCH
+               p.To.Offset = 4
+               q1 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AINT
+               p.From.Type = D_CONST
+               p.From.Offset = 3
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ANOP
+               q1.Pcond = p
+       }
+
+       q1 = nil
+
+       if framesize <= obj.StackSmall {
+               // small stack: SP <= stackguard
+               //      CMPL SP, stackguard
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ACMPL
+               p.From.Type = D_SP
+               p.To.Type = D_INDIR + D_CX
+               p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+       } else if framesize <= obj.StackBig {
+               // large stack: SP-framesize <= stackguard-StackSmall
+               //      LEAL -(framesize-StackSmall)(SP), AX
+               //      CMPL AX, stackguard
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ALEAL
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = -(int64(framesize) - obj.StackSmall)
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMPL
+               p.From.Type = D_AX
+               p.To.Type = D_INDIR + D_CX
+               p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+       } 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.
+               //      MOVL    stackguard, CX
+               //      CMPL    CX, $StackPreempt
+               //      JEQ     label-of-call-to-morestack
+               //      LEAL    StackGuard(SP), AX
+               //      SUBL    stackguard, AX
+               //      CMPL    AX, $(framesize+(StackGuard-StackSmall))
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVL
+               p.From.Type = D_INDIR + D_CX
+               p.From.Offset = 0
+               p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+               p.To.Type = D_SI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMPL
+               p.From.Type = D_SI
+               p.To.Type = D_CONST
+               p.To.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1)))
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJEQ
+               p.To.Type = D_BRANCH
+               q1 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ALEAL
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = obj.StackGuard
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ASUBL
+               p.From.Type = D_SI
+               p.From.Offset = 0
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMPL
+               p.From.Type = D_AX
+               p.To.Type = D_CONST
+               p.To.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+       }
+
+       // common
+       p = obj.Appendp(ctxt, p)
+
+       p.As = AJHI
+       p.To.Type = D_BRANCH
+       p.To.Offset = 4
+       q = p
+
+       p = obj.Appendp(ctxt, p)
+       p.As = ACALL
+       p.To.Type = D_BRANCH
+       if ctxt.Cursym.Cfunc != 0 {
+               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+       } else {
+
+               p.To.Sym = ctxt.Symmorestack[noctxt]
+       }
+
+       p = obj.Appendp(ctxt, p)
+       p.As = AJMP
+       p.To.Type = D_BRANCH
+       p.Pcond = ctxt.Cursym.Text.Link
+
+       if q != nil {
+               q.Pcond = p.Link
+       }
+       if q1 != nil {
+               q1.Pcond = q.Link
+       }
+
+       *jmpok = q
+       return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+       var firstp *obj.Prog
+       var lastp *obj.Prog
+
+       ctxt.Cursym = s
+
+       firstp = ctxt.NewProg()
+       lastp = firstp
+       xfol(ctxt, s.Text, &lastp)
+       lastp.Link = nil
+       s.Text = firstp.Link
+}
+
+func nofollow(a int) int {
+       switch a {
+       case AJMP,
+               ARET,
+               AIRETL,
+               AIRETW,
+               AUNDEF:
+               return 1
+       }
+
+       return 0
+}
+
+func pushpop(a int) int {
+       switch a {
+       case APUSHL,
+               APUSHFL,
+               APUSHW,
+               APUSHFW,
+               APOPL,
+               APOPFL,
+               APOPW,
+               APOPFW:
+               return 1
+       }
+
+       return 0
+}
+
+func relinv(a int) int {
+       switch a {
+       case AJEQ:
+               return AJNE
+       case AJNE:
+               return AJEQ
+       case AJLE:
+               return AJGT
+       case AJLS:
+               return AJHI
+       case AJLT:
+               return AJGE
+       case AJMI:
+               return AJPL
+       case AJGE:
+               return AJLT
+       case AJPL:
+               return AJMI
+       case AJGT:
+               return AJLE
+       case AJHI:
+               return AJLS
+       case AJCS:
+               return AJCC
+       case AJCC:
+               return AJCS
+       case AJPS:
+               return AJPC
+       case AJPC:
+               return AJPS
+       case AJOS:
+               return AJOC
+       case AJOC:
+               return AJOS
+       }
+
+       log.Fatalf("unknown relation: %s", Anames[a])
+       return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+       var q *obj.Prog
+       var i int
+       var a int
+
+loop:
+       if p == nil {
+               return
+       }
+       if p.As == AJMP {
+               q = p.Pcond
+               if q != nil && q.As != ATEXT {
+                       /* mark instruction as done and continue layout at target of jump */
+                       p.Mark = 1
+
+                       p = q
+                       if p.Mark == 0 {
+                               goto loop
+                       }
+               }
+       }
+
+       if p.Mark != 0 {
+               /*
+                * p goes here, but already used it elsewhere.
+                * copy up to 4 instructions or else branch to other copy.
+                */
+               i = 0
+               q = p
+               for ; i < 4; (func() { i++; q = q.Link })() {
+
+                       if q == nil {
+                               break
+                       }
+                       if q == *last {
+                               break
+                       }
+                       a = int(q.As)
+                       if a == ANOP {
+                               i--
+                               continue
+                       }
+
+                       if nofollow(a) != 0 || pushpop(a) != 0 {
+                               break // NOTE(rsc): arm does goto copy
+                       }
+                       if q.Pcond == nil || q.Pcond.Mark != 0 {
+                               continue
+                       }
+                       if a == ACALL || a == ALOOP {
+                               continue
+                       }
+                       for {
+                               if p.As == ANOP {
+                                       p = p.Link
+                                       continue
+                               }
+
+                               q = obj.Copyp(ctxt, p)
+                               p = p.Link
+                               q.Mark = 1
+                               (*last).Link = q
+                               *last = q
+                               if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+                                       continue
+                               }
+
+                               q.As = int16(relinv(int(q.As)))
+                               p = q.Pcond
+                               q.Pcond = q.Link
+                               q.Link = p
+                               xfol(ctxt, q.Link, last)
+                               p = q.Link
+                               if p.Mark != 0 {
+                                       return
+                               }
+                               goto loop
+                               /* */
+                       }
+               }
+               q = ctxt.NewProg()
+               q.As = AJMP
+               q.Lineno = p.Lineno
+               q.To.Type = D_BRANCH
+               q.To.Offset = p.Pc
+               q.Pcond = p
+               p = q
+       }
+
+       /* emit p */
+       p.Mark = 1
+
+       (*last).Link = p
+       *last = p
+       a = int(p.As)
+
+       /* continue loop with what comes after p */
+       if nofollow(a) != 0 {
+
+               return
+       }
+       if p.Pcond != nil && a != ACALL {
+               /*
+                * some kind of conditional branch.
+                * recurse to follow one path.
+                * continue loop on the other.
+                */
+               q = obj.Brchain(ctxt, p.Pcond)
+               if q != nil {
+
+                       p.Pcond = q
+               }
+               q = obj.Brchain(ctxt, p.Link)
+               if q != nil {
+                       p.Link = q
+               }
+               if p.From.Type == D_CONST {
+                       if p.From.Offset == 1 {
+                               /*
+                                * expect conditional jump to be taken.
+                                * rewrite so that's the fall-through case.
+                                */
+                               p.As = int16(relinv(a))
+
+                               q = p.Link
+                               p.Link = p.Pcond
+                               p.Pcond = q
+                       }
+               } else {
+
+                       q = p.Link
+                       if q.Mark != 0 {
+                               if a != ALOOP {
+                                       p.As = int16(relinv(a))
+                                       p.Link = p.Pcond
+                                       p.Pcond = q
+                               }
+                       }
+               }
+
+               xfol(ctxt, p.Link, last)
+               if p.Pcond.Mark != 0 {
+                       return
+               }
+               p = p.Pcond
+               goto loop
+       }
+
+       p = p.Link
+       goto loop
+}
+
+var Link386 = obj.LinkArch{
+       ByteOrder:     binary.LittleEndian,
+       Pconv:         Pconv,
+       Name:          "386",
+       Thechar:       '8',
+       Endian:        obj.LittleEndian,
+       Addstacksplit: addstacksplit,
+       Assemble:      span8,
+       Datasize:      datasize,
+       Follow:        follow,
+       Iscall:        iscall,
+       Isdata:        isdata,
+       Prg:           prg,
+       Progedit:      progedit,
+       Settextflag:   settextflag,
+       Symtype:       symtype,
+       Textflag:      textflag,
+       Minlc:         1,
+       Ptrsize:       4,
+       Regsize:       4,
+       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:         ACALL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          AJMP,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARET,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
diff --git a/src/cmd/internal/obj/i386/util.go b/src/cmd/internal/obj/i386/util.go
new file mode 100644 (file)
index 0000000..9f86766
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package i386
+
+const (
+       fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+       if b {
+               return 1
+       }
+       return 0
+}
diff --git a/src/cmd/internal/obj/ld.go b/src/cmd/internal/obj/ld.go
new file mode 100644 (file)
index 0000000..06dee83
--- /dev/null
@@ -0,0 +1,161 @@
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.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.
+
+package obj
+
+import (
+       "fmt"
+       "os"
+       "path"
+       "strings"
+)
+
+func addlib(ctxt *Link, src, obj, pathname string) {
+       name := path.Clean(pathname)
+
+       // runtime.a -> runtime
+       short := strings.TrimSuffix(name, ".a")
+
+       // already loaded?
+       for i := range ctxt.Library {
+               if ctxt.Library[i].Pkg == short {
+                       return
+               }
+       }
+
+       var pname string
+       // runtime -> runtime.a for search
+       if (!(ctxt.Windows != 0) && name[0] == '/') || (ctxt.Windows != 0 && name[1] == ':') {
+               pname = name
+       } else {
+               // try dot, -L "libdir", and then goroot.
+               for _, dir := range ctxt.Libdir {
+                       pname = dir + "/" + name
+                       if _, err := os.Stat(pname); !os.IsNotExist(err) {
+                               break
+                       }
+               }
+       }
+       pname = path.Clean(pname)
+
+       // runtime.a -> runtime
+       pname = strings.TrimSuffix(pname, ".a")
+
+       if ctxt.Debugvlog > 1 && ctxt.Bso != nil {
+               fmt.Fprintf(ctxt.Bso, "%5.2f addlib: %s %s pulls in %s\n", Cputime(), obj, src, pname)
+       }
+       addlibpath(ctxt, src, obj, pname, name)
+}
+
+/*
+ * add library to library list.
+ *     srcref: src file referring to package
+ *     objref: object file referring to package
+ *     file: object file, e.g., /home/rsc/go/pkg/container/vector.a
+ *     pkg: package import path, e.g. container/vector
+ */
+func addlibpath(ctxt *Link, srcref, objref, file, pkg string) {
+       for _, lib := range ctxt.Library {
+               if lib.File == file {
+                       return
+               }
+       }
+
+       if ctxt.Debugvlog > 1 && ctxt.Bso != nil {
+               fmt.Fprintf(ctxt.Bso, "%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s\n", Cputime(), srcref, objref, file, pkg)
+       }
+
+       ctxt.Library = append(ctxt.Library, Library{
+               Objref: objref,
+               Srcref: srcref,
+               File:   file,
+               Pkg:    pkg,
+       })
+}
+
+const (
+       LOG = 5
+)
+
+func mkfwd(sym *LSym) {
+       var p *Prog
+       var i int
+       var dwn [LOG]int32
+       var cnt [LOG]int32
+       var lst [LOG]*Prog
+
+       for i = 0; i < LOG; i++ {
+               if i == 0 {
+                       cnt[i] = 1
+               } else {
+
+                       cnt[i] = LOG * cnt[i-1]
+               }
+               dwn[i] = 1
+               lst[i] = nil
+       }
+
+       i = 0
+       for p = sym.Text; p != nil && p.Link != nil; p = p.Link {
+               i--
+               if i < 0 {
+                       i = LOG - 1
+               }
+               p.Forwd = nil
+               dwn[i]--
+               if dwn[i] <= 0 {
+                       dwn[i] = cnt[i]
+                       if lst[i] != nil {
+                               lst[i].Forwd = p
+                       }
+                       lst[i] = p
+               }
+       }
+}
+
+func Copyp(ctxt *Link, q *Prog) *Prog {
+       var p *Prog
+
+       p = ctxt.NewProg()
+       *p = *q
+       return p
+}
+
+func Appendp(ctxt *Link, q *Prog) *Prog {
+       var p *Prog
+
+       p = ctxt.NewProg()
+       p.Link = q.Link
+       q.Link = p
+       p.Lineno = q.Lineno
+       p.Mode = q.Mode
+       return p
+}
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
new file mode 100644 (file)
index 0000000..f2311f9
--- /dev/null
@@ -0,0 +1,463 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
+//
+//     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.
+
+package obj
+
+import "encoding/binary"
+
+type Addr struct {
+       Offset int64
+       U      struct {
+               Sval   string
+               Dval   float64
+               Branch *Prog
+       }
+       Sym     *LSym
+       Gotype  *LSym
+       Type    int16
+       Index   uint8
+       Scale   int8
+       Reg     int8
+       Name    int8
+       Class   int8
+       Etype   uint8
+       Offset2 int32
+       Node    interface{}
+       Width   int64
+}
+
+type Prog struct {
+       Ctxt     *Link
+       Pc       int64
+       Lineno   int32
+       Link     *Prog
+       As       int16
+       Scond    uint8
+       From     Addr
+       Reg      uint8
+       From3    Addr
+       To       Addr
+       Opt      interface{}
+       Forwd    *Prog
+       Pcond    *Prog
+       Comefrom *Prog
+       Pcrel    *Prog
+       Spadj    int32
+       Mark     uint16
+       Optab    uint16
+       Back     uint8
+       Ft       uint8
+       Tt       uint8
+       Isize    uint8
+       Printed  uint8
+       Width    int8
+       Mode     int8
+       TEXTFLAG uint8
+}
+
+type LSym struct {
+       Name        string
+       Extname     string
+       Type        int16
+       Version     int16
+       Dupok       uint8
+       Cfunc       uint8
+       External    uint8
+       Nosplit     uint8
+       Reachable   uint8
+       Cgoexport   uint8
+       Special     uint8
+       Stkcheck    uint8
+       Hide        uint8
+       Leaf        uint8
+       Fnptr       uint8
+       Localentry  uint8
+       Seenglobl   uint8
+       Onlist      uint8
+       Printed     uint8
+       Symid       int16
+       Dynid       int32
+       Sig         int32
+       Plt         int32
+       Got         int32
+       Align       int32
+       Elfsym      int32
+       Args        int32
+       Locals      int32
+       Value       int64
+       Size        int64
+       Hash        *LSym
+       Allsym      *LSym
+       Next        *LSym
+       Sub         *LSym
+       Outer       *LSym
+       Gotype      *LSym
+       Reachparent *LSym
+       Queue       *LSym
+       File        string
+       Dynimplib   string
+       Dynimpvers  string
+       Sect        *struct{}
+       Autom       *Auto
+       Text        *Prog
+       Etext       *Prog
+       Pcln        *Pcln
+       P           []byte
+       R           []Reloc
+}
+
+type Reloc struct {
+       Off     int32
+       Siz     uint8
+       Done    uint8
+       Type    int32
+       Variant int32
+       Add     int64
+       Xadd    int64
+       Sym     *LSym
+       Xsym    *LSym
+}
+
+type Auto struct {
+       Asym    *LSym
+       Link    *Auto
+       Aoffset int32
+       Type    int16
+       Gotype  *LSym
+}
+
+type Hist struct {
+       Link    *Hist
+       Name    string
+       Line    int32
+       Offset  int32
+       Printed uint8
+}
+
+type Link struct {
+       Thechar            int32
+       Thestring          string
+       Goarm              int32
+       Headtype           int
+       Arch               *LinkArch
+       Ignore             func(string) int32
+       Debugasm           int32
+       Debugline          int32
+       Debughist          int32
+       Debugread          int32
+       Debugvlog          int32
+       Debugstack         int32
+       Debugzerostack     int32
+       Debugdivmod        int32
+       Debugfloat         int32
+       Debugpcln          int32
+       Flag_shared        int32
+       Iself              int32
+       Bso                *Biobuf
+       Pathname           string
+       Windows            int32
+       Trimpath           string
+       Goroot             string
+       Goroot_final       string
+       Enforce_data_order int32
+       Hash               [LINKHASH]*LSym
+       Allsym             *LSym
+       Nsymbol            int32
+       Hist               *Hist
+       Ehist              *Hist
+       Plist              *Plist
+       Plast              *Plist
+       Sym_div            *LSym
+       Sym_divu           *LSym
+       Sym_mod            *LSym
+       Sym_modu           *LSym
+       Symmorestack       [2]*LSym
+       Tlsg               *LSym
+       Plan9privates      *LSym
+       Curp               *Prog
+       Printp             *Prog
+       Blitrl             *Prog
+       Elitrl             *Prog
+       Rexflag            int
+       Rep                int
+       Repn               int
+       Lock               int
+       Asmode             int
+       Andptr             []byte
+       And                [100]uint8
+       Instoffset         int64
+       Autosize           int32
+       Armsize            int32
+       Pc                 int64
+       Libdir             []string
+       Library            []Library
+       Tlsoffset          int
+       Diag               func(string, ...interface{})
+       Mode               int
+       Curauto            *Auto
+       Curhist            *Auto
+       Cursym             *LSym
+       Version            int
+       Textp              *LSym
+       Etextp             *LSym
+       Histdepth          int32
+       Nhistfile          int32
+       Filesyms           *LSym
+}
+
+type Plist struct {
+       Name    *LSym
+       Firstpc *Prog
+       Recur   int
+       Link    *Plist
+}
+
+type LinkArch struct {
+       Pconv         func(*Prog) string
+       Name          string
+       Thechar       int
+       Endian        int32
+       ByteOrder     binary.ByteOrder
+       Addstacksplit func(*Link, *LSym)
+       Assemble      func(*Link, *LSym)
+       Datasize      func(*Prog) int
+       Follow        func(*Link, *LSym)
+       Iscall        func(*Prog) bool
+       Isdata        func(*Prog) bool
+       Prg           func() *Prog
+       Progedit      func(*Link, *Prog)
+       Settextflag   func(*Prog, int)
+       Symtype       func(*Addr) int
+       Textflag      func(*Prog) int
+       Minlc         int
+       Ptrsize       int
+       Regsize       int
+       D_ADDR        int
+       D_AUTO        int
+       D_BRANCH      int
+       D_CONST       int
+       D_EXTERN      int
+       D_FCONST      int
+       D_NONE        int
+       D_PARAM       int
+       D_SCONST      int
+       D_STATIC      int
+       D_OREG        int
+       ACALL         int
+       ADATA         int
+       AEND          int
+       AFUNCDATA     int
+       AGLOBL        int
+       AJMP          int
+       ANOP          int
+       APCDATA       int
+       ARET          int
+       ATEXT         int
+       ATYPE         int
+       AUSEFIELD     int
+}
+
+type Library struct {
+       Objref string
+       Srcref string
+       File   string
+       Pkg    string
+}
+
+type Pcln struct {
+       Pcsp        Pcdata
+       Pcfile      Pcdata
+       Pcline      Pcdata
+       Pcdata      []Pcdata
+       Funcdata    []*LSym
+       Funcdataoff []int64
+       File        []*LSym
+       Lastfile    *LSym
+       Lastindex   int
+}
+
+type Pcdata struct {
+       P []byte
+}
+
+type Pciter struct {
+       d       Pcdata
+       p       []byte
+       pc      uint32
+       nextpc  uint32
+       pcscale uint32
+       value   int32
+       start   int
+       done    int
+}
+
+// prevent incompatible type signatures between liblink and 8l on Plan 9
+
+// prevent incompatible type signatures between liblink and 8l on Plan 9
+
+// LSym.type
+const (
+       Sxxx = iota
+       STEXT
+       SELFRXSECT
+       STYPE
+       SSTRING
+       SGOSTRING
+       SGOFUNC
+       SRODATA
+       SFUNCTAB
+       STYPELINK
+       SSYMTAB
+       SPCLNTAB
+       SELFROSECT
+       SMACHOPLT
+       SELFSECT
+       SMACHO
+       SMACHOGOT
+       SWINDOWS
+       SELFGOT
+       SNOPTRDATA
+       SINITARR
+       SDATA
+       SBSS
+       SNOPTRBSS
+       STLSBSS
+       SXREF
+       SMACHOSYMSTR
+       SMACHOSYMTAB
+       SMACHOINDIRECTPLT
+       SMACHOINDIRECTGOT
+       SFILE
+       SFILEPATH
+       SCONST
+       SDYNIMPORT
+       SHOSTOBJ
+       SSUB    = 1 << 8
+       SMASK   = SSUB - 1
+       SHIDDEN = 1 << 9
+)
+
+// Reloc.type
+const (
+       R_ADDR = 1 + iota
+       R_ADDRPOWER
+       R_SIZE
+       R_CALL
+       R_CALLARM
+       R_CALLIND
+       R_CALLPOWER
+       R_CONST
+       R_PCREL
+       R_TLS
+       R_TLS_LE
+       R_TLS_IE
+       R_GOTOFF
+       R_PLT0
+       R_PLT1
+       R_PLT2
+       R_USEFIELD
+       R_POWER_TOC
+)
+
+// Reloc.variant
+const (
+       RV_NONE = iota
+       RV_POWER_LO
+       RV_POWER_HI
+       RV_POWER_HA
+       RV_POWER_DS
+       RV_CHECK_OVERFLOW = 1 << 8
+       RV_TYPE_MASK      = RV_CHECK_OVERFLOW - 1
+)
+
+// Auto.type
+const (
+       A_AUTO = 1 + iota
+       A_PARAM
+)
+
+const (
+       LINKHASH = 100003
+)
+
+// Pcdata iterator.
+//     for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) }
+
+// symbol version, incremented each time a file is loaded.
+// version==1 is reserved for savehist.
+const (
+       HistVersion = 1
+)
+
+// Link holds the context for writing object code from a compiler
+// to be linker input or for reading that input into the linker.
+
+const (
+       LittleEndian = 0x04030201
+       BigEndian    = 0x01020304
+)
+
+// LinkArch is the definition of a single architecture.
+
+/* executable header types */
+const (
+       Hunknown = 0 + iota
+       Hdarwin
+       Hdragonfly
+       Helf
+       Hfreebsd
+       Hlinux
+       Hnacl
+       Hnetbsd
+       Hopenbsd
+       Hplan9
+       Hsolaris
+       Hwindows
+)
+
+const (
+       LinkAuto = 0 + iota
+       LinkInternal
+       LinkExternal
+)
+
+// asm5.c
+
+// asm6.c
+
+// asm8.c
+
+// asm9.c
+
+// data.c
+
+// go.c
+
+// ld.c
diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go
new file mode 100644 (file)
index 0000000..4d8d13c
--- /dev/null
@@ -0,0 +1,314 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+       "fmt"
+       "path/filepath"
+       "strings"
+)
+
+const (
+       HISTSZ = 10
+       NSYM   = 50
+)
+
+func linklinefmt(ctxt *Link, lno0 int, showAll, showFullPath bool) string {
+       var a [HISTSZ]struct {
+               incl *Hist
+               idel int32
+               line *Hist
+               ldel int32
+       }
+       lno := int32(lno0)
+       lno1 := lno
+       var d int32
+       var i int
+       var n int
+       var h *Hist
+       n = 0
+       var fp string
+       for h = ctxt.Hist; h != nil; h = h.Link {
+               if h.Offset < 0 {
+                       continue
+               }
+               if lno < h.Line {
+                       break
+               }
+               if h.Name != "<pop>" {
+                       if h.Offset > 0 {
+                               // #line directive
+                               if n > 0 && n < int(HISTSZ) {
+                                       a[n-1].line = h
+                                       a[n-1].ldel = h.Line - h.Offset + 1
+                               }
+                       } else {
+                               // beginning of file
+                               if n < int(HISTSZ) {
+                                       a[n].incl = h
+                                       a[n].idel = h.Line
+                                       a[n].line = nil
+                               }
+                               n++
+                       }
+                       continue
+               }
+               n--
+               if n > 0 && n < int(HISTSZ) {
+                       d = h.Line - a[n].incl.Line
+                       a[n-1].ldel += d
+                       a[n-1].idel += d
+               }
+       }
+       if n > int(HISTSZ) {
+               n = int(HISTSZ)
+       }
+       for i = n - 1; i >= 0; i-- {
+               if i != n-1 {
+                       if !showAll {
+                               break
+                       }
+                       fp += " "
+               }
+               if ctxt.Debugline != 0 || showFullPath {
+                       fp += fmt.Sprintf("%s/", ctxt.Pathname)
+               }
+               if a[i].line != nil {
+                       fp += fmt.Sprintf("%s:%d[%s:%d]", a[i].line.Name, lno-a[i].ldel+1, a[i].incl.Name, lno-a[i].idel+1)
+               } else {
+                       fp += fmt.Sprintf("%s:%d", a[i].incl.Name, lno-a[i].idel+1)
+               }
+               lno = a[i].incl.Line - 1 // now print out start of this file
+       }
+       if n == 0 {
+               fp += fmt.Sprintf("<unknown line number %d %d %d %s>", lno1, ctxt.Hist.Offset, ctxt.Hist.Line, ctxt.Hist.Name)
+       }
+       return fp
+}
+
+// Does s have t as a path prefix?
+// That is, does s == t or does s begin with t followed by a slash?
+// For portability, we allow ASCII case folding, so that haspathprefix("a/b/c", "A/B") is true.
+// Similarly, we allow slash folding, so that haspathprefix("a/b/c", "a\\b") is true.
+func haspathprefix(s string, t string) bool {
+       var i int
+       var cs int
+       var ct int
+       if len(t) > len(s) {
+               return false
+       }
+       for i = 0; i < len(t); i++ {
+               cs = int(s[i])
+               ct = int(t[i])
+               if 'A' <= cs && cs <= 'Z' {
+                       cs += 'a' - 'A'
+               }
+               if 'A' <= ct && ct <= 'Z' {
+                       ct += 'a' - 'A'
+               }
+               if cs == '\\' {
+                       cs = '/'
+               }
+               if ct == '\\' {
+                       ct = '/'
+               }
+               if cs != ct {
+                       return false
+               }
+       }
+       return i >= len(s) || s[i] == '/' || s[i] == '\\'
+}
+
+// This is a simplified copy of linklinefmt above.
+// It doesn't allow printing the full stack, and it returns the file name and line number separately.
+// TODO: Unify with linklinefmt somehow.
+func linkgetline(ctxt *Link, line int32, f **LSym, l *int32) {
+       var a [HISTSZ]struct {
+               incl *Hist
+               idel int32
+               line *Hist
+               ldel int32
+       }
+       var lno int32
+       var d int32
+       var dlno int32
+       var n int
+       var h *Hist
+       var buf string
+       var buf1 string
+       var file string
+       lno = int32(line)
+       n = 0
+       for h = ctxt.Hist; h != nil; h = h.Link {
+               if h.Offset < 0 {
+                       continue
+               }
+               if lno < h.Line {
+                       break
+               }
+               if h.Name != "<pop>" {
+                       if h.Offset > 0 {
+                               // #line directive
+                               if n > 0 && n < HISTSZ {
+                                       a[n-1].line = h
+                                       a[n-1].ldel = h.Line - h.Offset + 1
+                               }
+                       } else {
+                               // beginning of file
+                               if n < HISTSZ {
+                                       a[n].incl = h
+                                       a[n].idel = h.Line
+                                       a[n].line = nil
+                               }
+                               n++
+                       }
+                       continue
+               }
+               n--
+               if n > 0 && n < HISTSZ {
+                       d = h.Line - a[n].incl.Line
+                       a[n-1].ldel += d
+                       a[n-1].idel += d
+               }
+       }
+       if n > HISTSZ {
+               n = HISTSZ
+       }
+       if n <= 0 {
+               *f = Linklookup(ctxt, "??", HistVersion)
+               *l = 0
+               return
+       }
+       n--
+       if a[n].line != nil {
+               file = a[n].line.Name
+               dlno = a[n].ldel - 1
+       } else {
+               file = a[n].incl.Name
+               dlno = a[n].idel - 1
+       }
+       if filepath.IsAbs(file) || strings.HasPrefix(file, "<") {
+               buf = fmt.Sprintf("%s", file)
+       } else {
+               buf = fmt.Sprintf("%s/%s", ctxt.Pathname, file)
+       }
+       // Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL.
+       if ctxt.Trimpath != "" && haspathprefix(buf, ctxt.Trimpath) {
+               if len(buf) == len(ctxt.Trimpath) {
+                       buf = "??"
+               } else {
+                       buf1 = fmt.Sprintf("%s", buf[len(ctxt.Trimpath)+1:])
+                       if buf1[0] == '\x00' {
+                               buf1 = "??"
+                       }
+                       buf = buf1
+               }
+       } else if ctxt.Goroot_final != "" && haspathprefix(buf, ctxt.Goroot) {
+               buf1 = fmt.Sprintf("%s%s", ctxt.Goroot_final, buf[len(ctxt.Goroot):])
+               buf = buf1
+       }
+       lno -= dlno
+       *f = Linklookup(ctxt, buf, HistVersion)
+       *l = lno
+}
+
+func Linklinehist(ctxt *Link, lineno int, f string, offset int) {
+       var h *Hist
+
+       if false { // debug['f']
+               if f != "" {
+                       if offset != 0 {
+                               fmt.Printf("%4d: %s (#line %d)\n", lineno, f, offset)
+                       } else {
+
+                               fmt.Printf("%4d: %s\n", lineno, f)
+                       }
+               } else {
+
+                       fmt.Printf("%4d: <pop>\n", lineno)
+               }
+       }
+
+       h = new(Hist)
+       *h = Hist{}
+       h.Name = f
+       h.Line = int32(lineno)
+       h.Offset = int32(offset)
+       h.Link = nil
+       if ctxt.Ehist == nil {
+               ctxt.Hist = h
+               ctxt.Ehist = h
+               return
+       }
+
+       ctxt.Ehist.Link = h
+       ctxt.Ehist = h
+}
+
+func Linkprfile(ctxt *Link, line int) {
+       l := int32(line)
+       var i int
+       var n int
+       var a [HISTSZ]Hist
+       var h *Hist
+       var d int32
+       n = 0
+       for h = ctxt.Hist; h != nil; h = h.Link {
+               if l < h.Line {
+                       break
+               }
+               if h.Name != "<pop>" {
+                       if h.Offset == 0 {
+                               if n >= 0 && n < HISTSZ {
+                                       a[n] = *h
+                               }
+                               n++
+                               continue
+                       }
+                       if n > 0 && n < HISTSZ {
+                               if a[n-1].Offset == 0 {
+                                       a[n] = *h
+                                       n++
+                               } else {
+                                       a[n-1] = *h
+                               }
+                       }
+                       continue
+               }
+               n--
+               if n >= 0 && n < HISTSZ {
+                       d = h.Line - a[n].Line
+                       for i = 0; i < n; i++ {
+                               a[i].Line += d
+                       }
+               }
+       }
+       if n > HISTSZ {
+               n = HISTSZ
+       }
+       for i = 0; i < n; i++ {
+               fmt.Printf("%s:%d ", a[i].Name, int(l-a[i].Line+a[i].Offset+1))
+       }
+}
+
+/*
+ * start a new Prog list.
+ */
+func Linknewplist(ctxt *Link) *Plist {
+
+       var pl *Plist
+
+       pl = new(Plist)
+       *pl = Plist{}
+       if ctxt.Plist == nil {
+               ctxt.Plist = pl
+       } else {
+
+               ctxt.Plast.Link = pl
+       }
+       ctxt.Plast = pl
+
+       return pl
+}
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
new file mode 100644 (file)
index 0000000..f1e1701
--- /dev/null
@@ -0,0 +1,457 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+       "fmt"
+       "log"
+       "path/filepath"
+       "strings"
+)
+
+var outfile string
+
+// The Go and C compilers, and the assembler, call writeobj to write
+// out a Go object file.  The linker does not call this; the linker
+// does not write out object files.
+func Writeobjdirect(ctxt *Link, b *Biobuf) {
+
+       var flag int
+       var found int
+       var h *Hist
+       var s *LSym
+       var text *LSym
+       var etext *LSym
+       var curtext *LSym
+       var data *LSym
+       var edata *LSym
+       var pl *Plist
+       var p *Prog
+       var plink *Prog
+       var a *Auto
+
+       // Build list of symbols, and assign instructions to lists.
+       // Ignore ctxt->plist boundaries. There are no guarantees there,
+       // and the C compilers and assemblers just use one big list.
+       text = nil
+
+       curtext = nil
+       data = nil
+       etext = nil
+       edata = nil
+       for pl = ctxt.Plist; pl != nil; pl = pl.Link {
+               for p = pl.Firstpc; p != nil; p = plink {
+                       if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 {
+                               fmt.Printf("obj: %p %v\n", p, p)
+                       }
+                       plink = p.Link
+                       p.Link = nil
+
+                       if int(p.As) == ctxt.Arch.AEND {
+                               continue
+                       }
+
+                       if int(p.As) == ctxt.Arch.ATYPE {
+                               // Assume each TYPE instruction describes
+                               // a different local variable or parameter,
+                               // so no dedup.
+                               // Using only the TYPE instructions means
+                               // that we discard location information about local variables
+                               // in C and assembly functions; that information is inferred
+                               // from ordinary references, because there are no TYPE
+                               // instructions there. Without the type information, gdb can't
+                               // use the locations, so we don't bother to save them.
+                               // If something else could use them, we could arrange to
+                               // preserve them.
+                               if curtext == nil {
+
+                                       continue
+                               }
+                               a = new(Auto)
+                               a.Asym = p.From.Sym
+                               a.Aoffset = int32(p.From.Offset)
+                               a.Type = int16(ctxt.Arch.Symtype(&p.From))
+                               a.Gotype = p.From.Gotype
+                               a.Link = curtext.Autom
+                               curtext.Autom = a
+                               continue
+                       }
+
+                       if int(p.As) == ctxt.Arch.AGLOBL {
+                               s = p.From.Sym
+                               tmp6 := s.Seenglobl
+                               s.Seenglobl++
+                               if tmp6 != 0 {
+                                       fmt.Printf("duplicate %v\n", p)
+                               }
+                               if s.Onlist != 0 {
+                                       log.Fatalf("symbol %s listed multiple times", s.Name)
+                               }
+                               s.Onlist = 1
+                               if data == nil {
+                                       data = s
+                               } else {
+
+                                       edata.Next = s
+                               }
+                               s.Next = nil
+                               s.Size = p.To.Offset
+                               if s.Type == 0 || s.Type == SXREF {
+                                       s.Type = SBSS
+                               }
+                               flag = ctxt.Arch.Textflag(p)
+                               if flag&DUPOK != 0 {
+                                       s.Dupok = 1
+                               }
+                               if flag&RODATA != 0 {
+                                       s.Type = SRODATA
+                               } else if flag&NOPTR != 0 {
+                                       s.Type = SNOPTRBSS
+                               }
+                               edata = s
+                               continue
+                       }
+
+                       if int(p.As) == ctxt.Arch.ADATA {
+                               savedata(ctxt, p.From.Sym, p, "<input>")
+                               continue
+                       }
+
+                       if int(p.As) == ctxt.Arch.ATEXT {
+                               s = p.From.Sym
+                               if s == nil {
+                                       // func _() { }
+                                       curtext = nil
+
+                                       continue
+                               }
+
+                               if s.Text != nil {
+                                       log.Fatalf("duplicate TEXT for %s", s.Name)
+                               }
+                               if s.Onlist != 0 {
+                                       log.Fatalf("symbol %s listed multiple times", s.Name)
+                               }
+                               s.Onlist = 1
+                               if text == nil {
+                                       text = s
+                               } else {
+
+                                       etext.Next = s
+                               }
+                               etext = s
+                               flag = ctxt.Arch.Textflag(p)
+                               if flag&DUPOK != 0 {
+                                       s.Dupok = 1
+                               }
+                               if flag&NOSPLIT != 0 {
+                                       s.Nosplit = 1
+                               }
+                               s.Next = nil
+                               s.Type = STEXT
+                               s.Text = p
+                               s.Etext = p
+                               curtext = s
+                               continue
+                       }
+
+                       if int(p.As) == ctxt.Arch.AFUNCDATA {
+                               // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
+                               if curtext == nil { // func _() {}
+                                       continue
+                               }
+                               if p.To.Sym.Name == "go_args_stackmap" {
+                                       if int(p.From.Type) != ctxt.Arch.D_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps {
+                                               ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
+                                       }
+                                       p.To.Sym = Linklookup(ctxt, string(fmt.Sprintf("%s.args_stackmap", curtext.Name)), int(curtext.Version))
+                               }
+                       }
+
+                       if curtext == nil {
+                               continue
+                       }
+                       s = curtext
+                       s.Etext.Link = p
+                       s.Etext = p
+               }
+       }
+
+       // Add reference to Go arguments for C or assembly functions without them.
+       for s = text; s != nil; s = s.Next {
+
+               if !strings.HasPrefix(s.Name, "\"\".") {
+                       continue
+               }
+               found = 0
+               for p = s.Text; p != nil; p = p.Link {
+                       if int(p.As) == ctxt.Arch.AFUNCDATA && int(p.From.Type) == ctxt.Arch.D_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps {
+                               found = 1
+                               break
+                       }
+               }
+
+               if !(found != 0) {
+                       p = Appendp(ctxt, s.Text)
+                       p.As = int16(ctxt.Arch.AFUNCDATA)
+                       p.From.Type = int16(ctxt.Arch.D_CONST)
+                       p.From.Offset = FUNCDATA_ArgsPointerMaps
+                       if ctxt.Arch.Thechar == '6' || ctxt.Arch.Thechar == '8' {
+                               p.To.Type = int16(ctxt.Arch.D_EXTERN)
+                       } else {
+
+                               p.To.Type = int16(ctxt.Arch.D_OREG)
+                               p.To.Name = int8(ctxt.Arch.D_EXTERN)
+                       }
+
+                       p.To.Sym = Linklookup(ctxt, string(fmt.Sprintf("%s.args_stackmap", s.Name)), int(s.Version))
+               }
+       }
+
+       // Turn functions into machine code images.
+       for s = text; s != nil; s = s.Next {
+
+               mkfwd(s)
+               linkpatch(ctxt, s)
+               ctxt.Arch.Follow(ctxt, s)
+               ctxt.Arch.Addstacksplit(ctxt, s)
+               ctxt.Arch.Assemble(ctxt, s)
+               linkpcln(ctxt, s)
+       }
+
+       // Emit header.
+       Bputc(b, 0)
+
+       Bputc(b, 0)
+       fmt.Fprintf(b, "go13ld")
+       Bputc(b, 1) // version
+
+       // Emit autolib.
+       for h = ctxt.Hist; h != nil; h = h.Link {
+
+               if h.Offset < 0 {
+                       wrstring(b, h.Name)
+               }
+       }
+       wrstring(b, "")
+
+       // Emit symbols.
+       for s = text; s != nil; s = s.Next {
+
+               writesym(ctxt, b, s)
+       }
+       for s = data; s != nil; s = s.Next {
+               writesym(ctxt, b, s)
+       }
+
+       // Emit footer.
+       Bputc(b, 0xff)
+
+       Bputc(b, 0xff)
+       fmt.Fprintf(b, "go13ld")
+}
+
+func writesym(ctxt *Link, b *Biobuf, s *LSym) {
+       var r *Reloc
+       var i int
+       var j int
+       var c int
+       var n int
+       var pc *Pcln
+       var p *Prog
+       var a *Auto
+       var name string
+
+       if ctxt.Debugasm != 0 {
+               fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
+               if s.Version != 0 {
+                       fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
+               }
+               if s.Type != 0 {
+                       fmt.Fprintf(ctxt.Bso, "t=%d ", s.Type)
+               }
+               if s.Dupok != 0 {
+                       fmt.Fprintf(ctxt.Bso, "dupok ")
+               }
+               if s.Cfunc != 0 {
+                       fmt.Fprintf(ctxt.Bso, "cfunc ")
+               }
+               if s.Nosplit != 0 {
+                       fmt.Fprintf(ctxt.Bso, "nosplit ")
+               }
+               fmt.Fprintf(ctxt.Bso, "size=%d value=%d", int64(s.Size), int64(s.Value))
+               if s.Type == STEXT {
+                       fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x", uint64(s.Args), uint64(s.Locals))
+                       if s.Leaf != 0 {
+                               fmt.Fprintf(ctxt.Bso, " leaf")
+                       }
+               }
+
+               fmt.Fprintf(ctxt.Bso, "\n")
+               for p = s.Text; p != nil; p = p.Link {
+                       fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
+               }
+               for i = 0; i < len(s.P); {
+                       fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
+                       for j = i; j < i+16 && j < len(s.P); j++ {
+                               fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
+                       }
+                       for ; j < i+16; j++ {
+                               fmt.Fprintf(ctxt.Bso, "   ")
+                       }
+                       fmt.Fprintf(ctxt.Bso, "  ")
+                       for j = i; j < i+16 && j < len(s.P); j++ {
+                               c = int(s.P[j])
+                               if ' ' <= c && c <= 0x7e {
+                                       fmt.Fprintf(ctxt.Bso, "%c", c)
+                               } else {
+
+                                       fmt.Fprintf(ctxt.Bso, ".")
+                               }
+                       }
+
+                       fmt.Fprintf(ctxt.Bso, "\n")
+                       i += 16
+               }
+
+               for i = 0; i < len(s.R); i++ {
+                       r = &s.R[i]
+                       name = ""
+                       if r.Sym != nil {
+                               name = r.Sym.Name
+                       }
+                       if ctxt.Arch.Thechar == '5' || ctxt.Arch.Thechar == '9' {
+                               fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(int64(r.Add)))
+                       } else {
+
+                               fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, int64(r.Add))
+                       }
+               }
+       }
+
+       Bputc(b, 0xfe)
+       wrint(b, int64(s.Type))
+       wrstring(b, s.Name)
+       wrint(b, int64(s.Version))
+       wrint(b, int64(s.Dupok))
+       wrint(b, s.Size)
+       wrsym(b, s.Gotype)
+       wrdata(b, s.P)
+
+       wrint(b, int64(len(s.R)))
+       for i = 0; i < len(s.R); i++ {
+               r = &s.R[i]
+               wrint(b, int64(r.Off))
+               wrint(b, int64(r.Siz))
+               wrint(b, int64(r.Type))
+               wrint(b, r.Add)
+               wrint(b, r.Xadd)
+               wrsym(b, r.Sym)
+               wrsym(b, r.Xsym)
+       }
+
+       if s.Type == STEXT {
+               wrint(b, int64(s.Args))
+               wrint(b, int64(s.Locals))
+               wrint(b, int64(s.Nosplit))
+               wrint(b, int64(s.Leaf)|int64(s.Cfunc)<<1)
+               n = 0
+               for a = s.Autom; a != nil; a = a.Link {
+                       n++
+               }
+               wrint(b, int64(n))
+               for a = s.Autom; a != nil; a = a.Link {
+                       wrsym(b, a.Asym)
+                       wrint(b, int64(a.Aoffset))
+                       if int(a.Type) == ctxt.Arch.D_AUTO {
+                               wrint(b, A_AUTO)
+                       } else if int(a.Type) == ctxt.Arch.D_PARAM {
+                               wrint(b, A_PARAM)
+                       } else {
+
+                               log.Fatalf("%s: invalid local variable type %d", s.Name, a.Type)
+                       }
+                       wrsym(b, a.Gotype)
+               }
+
+               pc = s.Pcln
+               wrdata(b, pc.Pcsp.P)
+               wrdata(b, pc.Pcfile.P)
+               wrdata(b, pc.Pcline.P)
+               wrint(b, int64(len(pc.Pcdata)))
+               for i = 0; i < len(pc.Pcdata); i++ {
+                       wrdata(b, pc.Pcdata[i].P)
+               }
+               wrint(b, int64(len(pc.Funcdataoff)))
+               for i = 0; i < len(pc.Funcdataoff); i++ {
+                       wrsym(b, pc.Funcdata[i])
+               }
+               for i = 0; i < len(pc.Funcdataoff); i++ {
+                       wrint(b, pc.Funcdataoff[i])
+               }
+               wrint(b, int64(len(pc.File)))
+               for i = 0; i < len(pc.File); i++ {
+                       wrpathsym(ctxt, b, pc.File[i])
+               }
+       }
+}
+
+func wrint(b *Biobuf, sval int64) {
+       var uv uint64
+       var v uint64
+       var buf [10]uint8
+       var p []uint8
+       uv = (uint64(sval) << 1) ^ uint64(int64(sval>>63))
+       p = buf[:]
+       for v = uv; v >= 0x80; v >>= 7 {
+               p[0] = uint8(v | 0x80)
+               p = p[1:]
+       }
+       p[0] = uint8(v)
+       p = p[1:]
+       Bwrite(b, buf[:len(buf)-len(p)])
+}
+
+func wrstring(b *Biobuf, s string) {
+       wrint(b, int64(len(s)))
+       b.w.WriteString(s)
+}
+
+// wrpath writes a path just like a string, but on windows, it
+// translates '\\' to '/' in the process.
+func wrpath(ctxt *Link, b *Biobuf, p string) {
+       wrstring(b, filepath.ToSlash(p))
+}
+
+func wrdata(b *Biobuf, v []byte) {
+       wrint(b, int64(len(v)))
+       Bwrite(b, v)
+}
+
+func wrpathsym(ctxt *Link, b *Biobuf, s *LSym) {
+       if s == nil {
+               wrint(b, 0)
+               wrint(b, 0)
+               return
+       }
+
+       wrpath(ctxt, b, s.Name)
+       wrint(b, int64(s.Version))
+}
+
+func wrsym(b *Biobuf, s *LSym) {
+       if s == nil {
+               wrint(b, 0)
+               wrint(b, 0)
+               return
+       }
+
+       wrstring(b, s.Name)
+       wrint(b, int64(s.Version))
+}
+
+var startmagic string = "\x00\x00go13ld"
+
+var endmagic string = "\xff\xffgo13ld"
diff --git a/src/cmd/internal/obj/pass.go b/src/cmd/internal/obj/pass.go
new file mode 100644 (file)
index 0000000..a8c1c77
--- /dev/null
@@ -0,0 +1,129 @@
+// Inferno utils/6l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.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.
+
+package obj
+
+// Code and data passes.
+
+func Brchain(ctxt *Link, p *Prog) *Prog {
+
+       var i int
+
+       for i = 0; i < 20; i++ {
+               if p == nil || int(p.As) != ctxt.Arch.AJMP || p.Pcond == nil {
+                       return p
+               }
+               p = p.Pcond
+       }
+
+       return nil
+}
+
+func brloop(ctxt *Link, p *Prog) *Prog {
+       var c int
+       var q *Prog
+
+       c = 0
+       for q = p; q != nil; q = q.Pcond {
+               if int(q.As) != ctxt.Arch.AJMP || q.Pcond == nil {
+                       break
+               }
+               c++
+               if c >= 5000 {
+                       return nil
+               }
+       }
+
+       return q
+}
+
+func linkpatch(ctxt *Link, sym *LSym) {
+       var c int32
+       var name string
+       var p *Prog
+       var q *Prog
+
+       ctxt.Cursym = sym
+
+       for p = sym.Text; p != nil; p = p.Link {
+               if ctxt.Arch.Progedit != nil {
+                       ctxt.Arch.Progedit(ctxt, p)
+               }
+               if int(p.To.Type) != ctxt.Arch.D_BRANCH {
+                       continue
+               }
+               if p.To.U.Branch != nil {
+                       // TODO: Remove to.u.branch in favor of p->pcond.
+                       p.Pcond = p.To.U.Branch
+
+                       continue
+               }
+
+               if p.To.Sym != nil {
+                       continue
+               }
+               c = int32(p.To.Offset)
+               for q = sym.Text; q != nil; {
+                       if int64(c) == q.Pc {
+                               break
+                       }
+                       if q.Forwd != nil && int64(c) >= q.Forwd.Pc {
+                               q = q.Forwd
+                       } else {
+
+                               q = q.Link
+                       }
+               }
+
+               if q == nil {
+                       name = "<nil>"
+                       if p.To.Sym != nil {
+                               name = p.To.Sym.Name
+                       }
+                       ctxt.Diag("branch out of range (%#x)\n%v [%s]", uint32(c), p, name)
+                       p.To.Type = int16(ctxt.Arch.D_NONE)
+               }
+
+               p.To.U.Branch = q
+               p.Pcond = q
+       }
+
+       for p = sym.Text; p != nil; p = p.Link {
+               p.Mark = 0 /* initialization for follow */
+               if p.Pcond != nil {
+                       p.Pcond = brloop(ctxt, p.Pcond)
+                       if p.Pcond != nil {
+                               if int(p.To.Type) == ctxt.Arch.D_BRANCH {
+                                       p.To.Offset = p.Pcond.Pc
+                               }
+                       }
+               }
+       }
+}
diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go
new file mode 100644 (file)
index 0000000..32d9498
--- /dev/null
@@ -0,0 +1,370 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+       "fmt"
+       "log"
+)
+
+func addvarint(ctxt *Link, d *Pcdata, val uint32) {
+       var v uint32
+       for v = val; v >= 0x80; v >>= 7 {
+               d.P = append(d.P, uint8(v|0x80))
+       }
+       d.P = append(d.P, uint8(v))
+}
+
+// funcpctab writes to dst a pc-value table mapping the code in func to the values
+// returned by valfunc parameterized by arg. The invocation of valfunc to update the
+// current value is, for each p,
+//
+//     val = valfunc(func, val, p, 0, arg);
+//     record val as value at p->pc;
+//     val = valfunc(func, val, p, 1, arg);
+//
+// where func is the function, val is the current value, p is the instruction being
+// considered, and arg can be used to further parameterize valfunc.
+func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
+
+       var dbg int
+       var i int
+       var oldval int32
+       var val int32
+       var started int32
+       var delta uint32
+       var pc int64
+       var p *Prog
+
+       // To debug a specific function, uncomment second line and change name.
+       dbg = 0
+
+       //dbg = strcmp(func->name, "main.main") == 0;
+       //dbg = strcmp(desc, "pctofile") == 0;
+
+       ctxt.Debugpcln += int32(dbg)
+
+       dst.P = dst.P[:0]
+
+       if ctxt.Debugpcln != 0 {
+               fmt.Fprintf(ctxt.Bso, "funcpctab %s [valfunc=%s]\n", func_.Name, desc)
+       }
+
+       val = -1
+       oldval = val
+       if func_.Text == nil {
+               ctxt.Debugpcln -= int32(dbg)
+               return
+       }
+
+       pc = func_.Text.Pc
+
+       if ctxt.Debugpcln != 0 {
+               fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(pc), val, func_.Text)
+       }
+
+       started = 0
+       for p = func_.Text; p != nil; p = p.Link {
+               // Update val. If it's not changing, keep going.
+               val = valfunc(ctxt, func_, val, p, 0, arg)
+
+               if val == oldval && started != 0 {
+                       val = valfunc(ctxt, func_, val, p, 1, arg)
+                       if ctxt.Debugpcln != 0 {
+                               fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p)
+                       }
+                       continue
+               }
+
+               // If the pc of the next instruction is the same as the
+               // pc of this instruction, this instruction is not a real
+               // instruction. Keep going, so that we only emit a delta
+               // for a true instruction boundary in the program.
+               if p.Link != nil && p.Link.Pc == p.Pc {
+
+                       val = valfunc(ctxt, func_, val, p, 1, arg)
+                       if ctxt.Debugpcln != 0 {
+                               fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p)
+                       }
+                       continue
+               }
+
+               // The table is a sequence of (value, pc) pairs, where each
+               // pair states that the given value is in effect from the current position
+               // up to the given pc, which becomes the new current position.
+               // To generate the table as we scan over the program instructions,
+               // we emit a "(value" when pc == func->value, and then
+               // each time we observe a change in value we emit ", pc) (value".
+               // When the scan is over, we emit the closing ", pc)".
+               //
+               // The table is delta-encoded. The value deltas are signed and
+               // transmitted in zig-zag form, where a complement bit is placed in bit 0,
+               // and the pc deltas are unsigned. Both kinds of deltas are sent
+               // as variable-length little-endian base-128 integers,
+               // where the 0x80 bit indicates that the integer continues.
+
+               if ctxt.Debugpcln != 0 {
+
+                       fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(int64(p.Pc)), val, p)
+               }
+
+               if started != 0 {
+                       addvarint(ctxt, dst, uint32((p.Pc-pc)/int64(ctxt.Arch.Minlc)))
+                       pc = p.Pc
+               }
+
+               delta = uint32(val) - uint32(oldval)
+               if delta>>31 != 0 {
+                       delta = 1 | ^(delta << 1)
+               } else {
+
+                       delta <<= 1
+               }
+               addvarint(ctxt, dst, delta)
+               oldval = val
+               started = 1
+               val = valfunc(ctxt, func_, val, p, 1, arg)
+       }
+
+       if started != 0 {
+               if ctxt.Debugpcln != 0 {
+                       fmt.Fprintf(ctxt.Bso, "%6x done\n", uint64(int64(func_.Text.Pc)+func_.Size))
+               }
+               addvarint(ctxt, dst, uint32((func_.Value+func_.Size-pc)/int64(ctxt.Arch.Minlc)))
+               addvarint(ctxt, dst, 0) // terminator
+       }
+
+       if ctxt.Debugpcln != 0 {
+               fmt.Fprintf(ctxt.Bso, "wrote %d bytes to %p\n", len(dst.P), dst)
+               for i = 0; i < len(dst.P); i++ {
+                       fmt.Fprintf(ctxt.Bso, " %02x", dst.P[i])
+               }
+               fmt.Fprintf(ctxt.Bso, "\n")
+       }
+
+       ctxt.Debugpcln -= int32(dbg)
+}
+
+// pctofileline computes either the file number (arg == 0)
+// or the line number (arg == 1) to use at p.
+// Because p->lineno applies to p, phase == 0 (before p)
+// takes care of the update.
+func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+       var i int32
+       var l int32
+       var f *LSym
+       var pcln *Pcln
+
+       if int(p.As) == ctxt.Arch.ATEXT || int(p.As) == ctxt.Arch.ANOP || int(p.As) == ctxt.Arch.AUSEFIELD || p.Lineno == 0 || phase == 1 {
+               return oldval
+       }
+       linkgetline(ctxt, p.Lineno, &f, &l)
+       if f == nil {
+               //      print("getline failed for %s %P\n", ctxt->cursym->name, p);
+               return oldval
+       }
+
+       if arg == nil {
+               return l
+       }
+       pcln = arg.(*Pcln)
+
+       if f == pcln.Lastfile {
+               return int32(pcln.Lastindex)
+       }
+
+       for i = 0; i < int32(len(pcln.File)); i++ {
+               file := pcln.File[i]
+               if file == f {
+                       pcln.Lastfile = f
+                       pcln.Lastindex = int(i)
+                       return int32(i)
+               }
+       }
+       pcln.File = append(pcln.File, f)
+       pcln.Lastfile = f
+       pcln.Lastindex = int(i)
+       return i
+}
+
+// pctospadj computes the sp adjustment in effect.
+// It is oldval plus any adjustment made by p itself.
+// The adjustment by p takes effect only after p, so we
+// apply the change during phase == 1.
+func pctospadj(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+       if oldval == -1 { // starting
+               oldval = 0
+       }
+       if phase == 0 {
+               return oldval
+       }
+       if oldval+p.Spadj < -10000 || oldval+p.Spadj > 1100000000 {
+               ctxt.Diag("overflow in spadj: %d + %d = %d", oldval, p.Spadj, oldval+p.Spadj)
+               log.Fatalf("bad code")
+       }
+
+       return oldval + p.Spadj
+}
+
+// pctopcdata computes the pcdata value in effect at p.
+// A PCDATA instruction sets the value in effect at future
+// non-PCDATA instructions.
+// Since PCDATA instructions have no width in the final code,
+// it does not matter which phase we use for the update.
+func pctopcdata(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+       if phase == 0 || int(p.As) != ctxt.Arch.APCDATA || p.From.Offset != int64(arg.(uint32)) {
+               return oldval
+       }
+       if int64(int32(p.To.Offset)) != p.To.Offset {
+               ctxt.Diag("overflow in PCDATA instruction: %v", p)
+               log.Fatalf("bad code")
+       }
+
+       return int32(p.To.Offset)
+}
+
+func linkpcln(ctxt *Link, cursym *LSym) {
+       var p *Prog
+       var pcln *Pcln
+       var i int
+       var npcdata int
+       var nfuncdata int
+
+       ctxt.Cursym = cursym
+
+       pcln = new(Pcln)
+       cursym.Pcln = pcln
+
+       npcdata = 0
+       nfuncdata = 0
+       for p = cursym.Text; p != nil; p = p.Link {
+               if int(p.As) == ctxt.Arch.APCDATA && p.From.Offset >= int64(npcdata) {
+                       npcdata = int(p.From.Offset + 1)
+               }
+               if int(p.As) == ctxt.Arch.AFUNCDATA && p.From.Offset >= int64(nfuncdata) {
+                       nfuncdata = int(p.From.Offset + 1)
+               }
+       }
+
+       pcln.Pcdata = make([]Pcdata, npcdata)
+       pcln.Pcdata = pcln.Pcdata[:npcdata]
+       pcln.Funcdata = make([]*LSym, nfuncdata)
+       pcln.Funcdataoff = make([]int64, nfuncdata)
+       pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
+
+       funcpctab(ctxt, &pcln.Pcsp, cursym, "pctospadj", pctospadj, nil)
+       funcpctab(ctxt, &pcln.Pcfile, cursym, "pctofile", pctofileline, pcln)
+       funcpctab(ctxt, &pcln.Pcline, cursym, "pctoline", pctofileline, nil)
+
+       // tabulate which pc and func data we have.
+       havepc := make([]uint32, (npcdata+31)/32)
+       havefunc := make([]uint32, (nfuncdata+31)/32)
+       for p = cursym.Text; p != nil; p = p.Link {
+               if int(p.As) == ctxt.Arch.AFUNCDATA {
+                       if (havefunc[p.From.Offset/32]>>uint64(p.From.Offset%32))&1 != 0 {
+                               ctxt.Diag("multiple definitions for FUNCDATA $%d", p.From.Offset)
+                       }
+                       havefunc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
+               }
+
+               if int(p.As) == ctxt.Arch.APCDATA {
+                       havepc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
+               }
+       }
+
+       // pcdata.
+       for i = 0; i < npcdata; i++ {
+
+               if (havepc[i/32]>>uint(i%32))&1 == 0 {
+                       continue
+               }
+               funcpctab(ctxt, &pcln.Pcdata[i], cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))
+       }
+
+       // funcdata
+       if nfuncdata > 0 {
+
+               for p = cursym.Text; p != nil; p = p.Link {
+                       if int(p.As) == ctxt.Arch.AFUNCDATA {
+                               i = int(p.From.Offset)
+                               pcln.Funcdataoff[i] = p.To.Offset
+                               if int(p.To.Type) != ctxt.Arch.D_CONST {
+                                       // TODO: Dedup.
+                                       //funcdata_bytes += p->to.sym->size;
+                                       pcln.Funcdata[i] = p.To.Sym
+                               }
+                       }
+               }
+       }
+}
+
+// iteration over encoded pcdata tables.
+
+func getvarint(pp *[]byte) uint32 {
+
+       var p []byte
+       var shift int
+       var v uint32
+
+       v = 0
+       p = *pp
+       for shift = 0; ; shift += 7 {
+               v |= uint32(p[0]&0x7F) << uint(shift)
+               tmp7 := p
+               p = p[1:]
+               if !(tmp7[0]&0x80 != 0) {
+                       break
+               }
+       }
+
+       *pp = p
+       return v
+}
+
+func pciternext(it *Pciter) {
+       var v uint32
+       var dv int32
+
+       it.pc = it.nextpc
+       if it.done != 0 {
+               return
+       }
+       if -cap(it.p) >= -cap(it.d.P[len(it.d.P):]) {
+               it.done = 1
+               return
+       }
+
+       // value delta
+       v = getvarint(&it.p)
+
+       if v == 0 && !(it.start != 0) {
+               it.done = 1
+               return
+       }
+
+       it.start = 0
+       dv = int32(v>>1) ^ (int32(v<<31) >> 31)
+       it.value += dv
+
+       // pc delta
+       v = getvarint(&it.p)
+
+       it.nextpc = it.pc + v*it.pcscale
+}
+
+func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) {
+       it.d = *d
+       it.p = it.d.P
+       it.pc = 0
+       it.nextpc = 0
+       it.value = -1
+       it.start = 1
+       it.done = 0
+       it.pcscale = uint32(ctxt.Arch.Minlc)
+       pciternext(it)
+}
diff --git a/src/cmd/internal/obj/ppc64/9.out.go b/src/cmd/internal/obj/ppc64/9.out.go
new file mode 100644 (file)
index 0000000..3c20b93
--- /dev/null
@@ -0,0 +1,485 @@
+// cmd/9c/9.out.h 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.
+
+package ppc64
+
+// auto generated by go tool dist
+
+/*
+ * powerpc 64
+ */
+const (
+       NSNAME = 8
+       NSYM   = 50
+       NREG   = 32
+       NFREG  = 32
+)
+
+const (
+       REGZERO  = 0
+       REGSP    = 1
+       REGSB    = 2
+       REGRET   = 3
+       REGARG   = -1
+       REGRT1   = 3
+       REGRT2   = 4
+       REGMIN   = 7
+       REGENV   = 11
+       REGTLS   = 13
+       REGMAX   = 27
+       REGEXT   = 30
+       REGG     = 30
+       REGTMP   = 31
+       FREGRET  = 0
+       FREGMIN  = 17
+       FREGMAX  = 26
+       FREGEXT  = 26
+       FREGCVI  = 27
+       FREGZERO = 28
+       FREGHALF = 29
+       FREGONE  = 30
+       FREGTWO  = 31
+)
+
+/*
+ * GENERAL:
+ *
+ * compiler allocates R3 up as temps
+ * compiler allocates register variables R7-R27
+ * compiler allocates external registers R30 down
+ *
+ * compiler allocates register variables F17-F26
+ * compiler allocates external registers F26 down
+ */
+const (
+       BIG = 32768 - 8
+)
+
+const (
+       LABEL   = 1 << 0
+       LEAF    = 1 << 1
+       FLOAT   = 1 << 2
+       BRANCH  = 1 << 3
+       LOAD    = 1 << 4
+       FCMP    = 1 << 5
+       SYNC    = 1 << 6
+       LIST    = 1 << 7
+       FOLL    = 1 << 8
+       NOSCHED = 1 << 9
+)
+
+const (
+       C_NONE = iota
+       C_REG
+       C_FREG
+       C_CREG
+       C_SPR
+       C_ZCON
+       C_SCON
+       C_UCON
+       C_ADDCON
+       C_ANDCON
+       C_LCON
+       C_DCON
+       C_SACON
+       C_SECON
+       C_LACON
+       C_LECON
+       C_DACON
+       C_SBRA
+       C_LBRA
+       C_SAUTO
+       C_LAUTO
+       C_SEXT
+       C_LEXT
+       C_ZOREG
+       C_SOREG
+       C_LOREG
+       C_FPSCR
+       C_MSR
+       C_XER
+       C_LR
+       C_CTR
+       C_ANY
+       C_GOK
+       C_ADDR
+       C_NCLASS
+)
+
+const (
+       AXXX = iota
+       AADD
+       AADDCC
+       AADDV
+       AADDVCC
+       AADDC
+       AADDCCC
+       AADDCV
+       AADDCVCC
+       AADDME
+       AADDMECC
+       AADDMEVCC
+       AADDMEV
+       AADDE
+       AADDECC
+       AADDEVCC
+       AADDEV
+       AADDZE
+       AADDZECC
+       AADDZEVCC
+       AADDZEV
+       AAND
+       AANDCC
+       AANDN
+       AANDNCC
+       ABC
+       ABCL
+       ABEQ
+       ABGE
+       ABGT
+       ABL
+       ABLE
+       ABLT
+       ABNE
+       ABR
+       ABVC
+       ABVS
+       ACMP
+       ACMPU
+       ACNTLZW
+       ACNTLZWCC
+       ACRAND
+       ACRANDN
+       ACREQV
+       ACRNAND
+       ACRNOR
+       ACROR
+       ACRORN
+       ACRXOR
+       ADIVW
+       ADIVWCC
+       ADIVWVCC
+       ADIVWV
+       ADIVWU
+       ADIVWUCC
+       ADIVWUVCC
+       ADIVWUV
+       AEQV
+       AEQVCC
+       AEXTSB
+       AEXTSBCC
+       AEXTSH
+       AEXTSHCC
+       AFABS
+       AFABSCC
+       AFADD
+       AFADDCC
+       AFADDS
+       AFADDSCC
+       AFCMPO
+       AFCMPU
+       AFCTIW
+       AFCTIWCC
+       AFCTIWZ
+       AFCTIWZCC
+       AFDIV
+       AFDIVCC
+       AFDIVS
+       AFDIVSCC
+       AFMADD
+       AFMADDCC
+       AFMADDS
+       AFMADDSCC
+       AFMOVD
+       AFMOVDCC
+       AFMOVDU
+       AFMOVS
+       AFMOVSU
+       AFMSUB
+       AFMSUBCC
+       AFMSUBS
+       AFMSUBSCC
+       AFMUL
+       AFMULCC
+       AFMULS
+       AFMULSCC
+       AFNABS
+       AFNABSCC
+       AFNEG
+       AFNEGCC
+       AFNMADD
+       AFNMADDCC
+       AFNMADDS
+       AFNMADDSCC
+       AFNMSUB
+       AFNMSUBCC
+       AFNMSUBS
+       AFNMSUBSCC
+       AFRSP
+       AFRSPCC
+       AFSUB
+       AFSUBCC
+       AFSUBS
+       AFSUBSCC
+       AMOVMW
+       ALSW
+       ALWAR
+       AMOVWBR
+       AMOVB
+       AMOVBU
+       AMOVBZ
+       AMOVBZU
+       AMOVH
+       AMOVHBR
+       AMOVHU
+       AMOVHZ
+       AMOVHZU
+       AMOVW
+       AMOVWU
+       AMOVFL
+       AMOVCRFS
+       AMTFSB0
+       AMTFSB0CC
+       AMTFSB1
+       AMTFSB1CC
+       AMULHW
+       AMULHWCC
+       AMULHWU
+       AMULHWUCC
+       AMULLW
+       AMULLWCC
+       AMULLWVCC
+       AMULLWV
+       ANAND
+       ANANDCC
+       ANEG
+       ANEGCC
+       ANEGVCC
+       ANEGV
+       ANOR
+       ANORCC
+       AOR
+       AORCC
+       AORN
+       AORNCC
+       AREM
+       AREMCC
+       AREMV
+       AREMVCC
+       AREMU
+       AREMUCC
+       AREMUV
+       AREMUVCC
+       ARFI
+       ARLWMI
+       ARLWMICC
+       ARLWNM
+       ARLWNMCC
+       ASLW
+       ASLWCC
+       ASRW
+       ASRAW
+       ASRAWCC
+       ASRWCC
+       ASTSW
+       ASTWCCC
+       ASUB
+       ASUBCC
+       ASUBVCC
+       ASUBC
+       ASUBCCC
+       ASUBCV
+       ASUBCVCC
+       ASUBME
+       ASUBMECC
+       ASUBMEVCC
+       ASUBMEV
+       ASUBV
+       ASUBE
+       ASUBECC
+       ASUBEV
+       ASUBEVCC
+       ASUBZE
+       ASUBZECC
+       ASUBZEVCC
+       ASUBZEV
+       ASYNC
+       AXOR
+       AXORCC
+       ADCBF
+       ADCBI
+       ADCBST
+       ADCBT
+       ADCBTST
+       ADCBZ
+       AECIWX
+       AECOWX
+       AEIEIO
+       AICBI
+       AISYNC
+       APTESYNC
+       ATLBIE
+       ATLBIEL
+       ATLBSYNC
+       ATW
+       ASYSCALL
+       ADATA
+       AGLOBL
+       AGOK
+       AHISTORY
+       ANAME
+       ANOP
+       ARETURN
+       ATEXT
+       AWORD
+       AEND
+       ADYNT
+       AINIT
+       ASIGNAME
+       ARFCI
+       AFRES
+       AFRESCC
+       AFRSQRTE
+       AFRSQRTECC
+       AFSEL
+       AFSELCC
+       AFSQRT
+       AFSQRTCC
+       AFSQRTS
+       AFSQRTSCC
+       ACNTLZD
+       ACNTLZDCC
+       ACMPW
+       ACMPWU
+       ADIVD
+       ADIVDCC
+       ADIVDVCC
+       ADIVDV
+       ADIVDU
+       ADIVDUCC
+       ADIVDUVCC
+       ADIVDUV
+       AEXTSW
+       AEXTSWCC
+       AFCFID
+       AFCFIDCC
+       AFCTID
+       AFCTIDCC
+       AFCTIDZ
+       AFCTIDZCC
+       ALDAR
+       AMOVD
+       AMOVDU
+       AMOVWZ
+       AMOVWZU
+       AMULHD
+       AMULHDCC
+       AMULHDU
+       AMULHDUCC
+       AMULLD
+       AMULLDCC
+       AMULLDVCC
+       AMULLDV
+       ARFID
+       ARLDMI
+       ARLDMICC
+       ARLDC
+       ARLDCCC
+       ARLDCR
+       ARLDCRCC
+       ARLDCL
+       ARLDCLCC
+       ASLBIA
+       ASLBIE
+       ASLBMFEE
+       ASLBMFEV
+       ASLBMTE
+       ASLD
+       ASLDCC
+       ASRD
+       ASRAD
+       ASRADCC
+       ASRDCC
+       ASTDCCC
+       ATD
+       ADWORD
+       AREMD
+       AREMDCC
+       AREMDV
+       AREMDVCC
+       AREMDU
+       AREMDUCC
+       AREMDUV
+       AREMDUVCC
+       AHRFID
+       AUNDEF
+       AUSEFIELD
+       ATYPE
+       AFUNCDATA
+       APCDATA
+       ACHECKNIL
+       AVARDEF
+       AVARKILL
+       ADUFFCOPY
+       ADUFFZERO
+       ALAST
+)
+
+/* type/name */
+const (
+       D_GOK = 0 + iota
+       D_NONE
+       D_EXTERN
+       D_STATIC
+       D_AUTO
+       D_PARAM
+       D_BRANCH
+       D_OREG
+       D_CONST
+       D_FCONST
+       D_SCONST
+       D_REG
+       D_FPSCR
+       D_MSR
+       D_FREG
+       D_CREG
+       D_SPR
+       D_OPT
+       D_FILE
+       D_FILE1
+       D_DCR
+       D_DCONST
+       D_ADDR
+       D_LAST
+       D_R0  = 0
+       D_F0  = D_R0 + NREG
+       D_XER = 1
+       D_LR  = 8
+       D_CTR = 9
+)
diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go
new file mode 100644 (file)
index 0000000..431c3fa
--- /dev/null
@@ -0,0 +1,389 @@
+package ppc64
+
+/* and many supervisor level registers */
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+       "XXX",
+       "ADD",
+       "ADDCC",
+       "ADDV",
+       "ADDVCC",
+       "ADDC",
+       "ADDCCC",
+       "ADDCV",
+       "ADDCVCC",
+       "ADDME",
+       "ADDMECC",
+       "ADDMEVCC",
+       "ADDMEV",
+       "ADDE",
+       "ADDECC",
+       "ADDEVCC",
+       "ADDEV",
+       "ADDZE",
+       "ADDZECC",
+       "ADDZEVCC",
+       "ADDZEV",
+       "AND",
+       "ANDCC",
+       "ANDN",
+       "ANDNCC",
+       "BC",
+       "BCL",
+       "BEQ",
+       "BGE",
+       "BGT",
+       "BL",
+       "BLE",
+       "BLT",
+       "BNE",
+       "BR",
+       "BVC",
+       "BVS",
+       "CMP",
+       "CMPU",
+       "CNTLZW",
+       "CNTLZWCC",
+       "CRAND",
+       "CRANDN",
+       "CREQV",
+       "CRNAND",
+       "CRNOR",
+       "CROR",
+       "CRORN",
+       "CRXOR",
+       "DIVW",
+       "DIVWCC",
+       "DIVWVCC",
+       "DIVWV",
+       "DIVWU",
+       "DIVWUCC",
+       "DIVWUVCC",
+       "DIVWUV",
+       "EQV",
+       "EQVCC",
+       "EXTSB",
+       "EXTSBCC",
+       "EXTSH",
+       "EXTSHCC",
+       "FABS",
+       "FABSCC",
+       "FADD",
+       "FADDCC",
+       "FADDS",
+       "FADDSCC",
+       "FCMPO",
+       "FCMPU",
+       "FCTIW",
+       "FCTIWCC",
+       "FCTIWZ",
+       "FCTIWZCC",
+       "FDIV",
+       "FDIVCC",
+       "FDIVS",
+       "FDIVSCC",
+       "FMADD",
+       "FMADDCC",
+       "FMADDS",
+       "FMADDSCC",
+       "FMOVD",
+       "FMOVDCC",
+       "FMOVDU",
+       "FMOVS",
+       "FMOVSU",
+       "FMSUB",
+       "FMSUBCC",
+       "FMSUBS",
+       "FMSUBSCC",
+       "FMUL",
+       "FMULCC",
+       "FMULS",
+       "FMULSCC",
+       "FNABS",
+       "FNABSCC",
+       "FNEG",
+       "FNEGCC",
+       "FNMADD",
+       "FNMADDCC",
+       "FNMADDS",
+       "FNMADDSCC",
+       "FNMSUB",
+       "FNMSUBCC",
+       "FNMSUBS",
+       "FNMSUBSCC",
+       "FRSP",
+       "FRSPCC",
+       "FSUB",
+       "FSUBCC",
+       "FSUBS",
+       "FSUBSCC",
+       "MOVMW",
+       "LSW",
+       "LWAR",
+       "MOVWBR",
+       "MOVB",
+       "MOVBU",
+       "MOVBZ",
+       "MOVBZU",
+       "MOVH",
+       "MOVHBR",
+       "MOVHU",
+       "MOVHZ",
+       "MOVHZU",
+       "MOVW",
+       "MOVWU",
+       "MOVFL",
+       "MOVCRFS",
+       "MTFSB0",
+       "MTFSB0CC",
+       "MTFSB1",
+       "MTFSB1CC",
+       "MULHW",
+       "MULHWCC",
+       "MULHWU",
+       "MULHWUCC",
+       "MULLW",
+       "MULLWCC",
+       "MULLWVCC",
+       "MULLWV",
+       "NAND",
+       "NANDCC",
+       "NEG",
+       "NEGCC",
+       "NEGVCC",
+       "NEGV",
+       "NOR",
+       "NORCC",
+       "OR",
+       "ORCC",
+       "ORN",
+       "ORNCC",
+       "REM",
+       "REMCC",
+       "REMV",
+       "REMVCC",
+       "REMU",
+       "REMUCC",
+       "REMUV",
+       "REMUVCC",
+       "RFI",
+       "RLWMI",
+       "RLWMICC",
+       "RLWNM",
+       "RLWNMCC",
+       "SLW",
+       "SLWCC",
+       "SRW",
+       "SRAW",
+       "SRAWCC",
+       "SRWCC",
+       "STSW",
+       "STWCCC",
+       "SUB",
+       "SUBCC",
+       "SUBVCC",
+       "SUBC",
+       "SUBCCC",
+       "SUBCV",
+       "SUBCVCC",
+       "SUBME",
+       "SUBMECC",
+       "SUBMEVCC",
+       "SUBMEV",
+       "SUBV",
+       "SUBE",
+       "SUBECC",
+       "SUBEV",
+       "SUBEVCC",
+       "SUBZE",
+       "SUBZECC",
+       "SUBZEVCC",
+       "SUBZEV",
+       "SYNC",
+       "XOR",
+       "XORCC",
+       "DCBF",
+       "DCBI",
+       "DCBST",
+       "DCBT",
+       "DCBTST",
+       "DCBZ",
+       "ECIWX",
+       "ECOWX",
+       "EIEIO",
+       "ICBI",
+       "ISYNC",
+       "PTESYNC",
+       "TLBIE",
+       "TLBIEL",
+       "TLBSYNC",
+       "TW",
+       "SYSCALL",
+       "DATA",
+       "GLOBL",
+       "GOK",
+       "HISTORY",
+       "NAME",
+       "NOP",
+       "RETURN",
+       "TEXT",
+       "WORD",
+       "END",
+       "DYNT",
+       "INIT",
+       "SIGNAME",
+       "RFCI",
+       "FRES",
+       "FRESCC",
+       "FRSQRTE",
+       "FRSQRTECC",
+       "FSEL",
+       "FSELCC",
+       "FSQRT",
+       "FSQRTCC",
+       "FSQRTS",
+       "FSQRTSCC",
+       "CNTLZD",
+       "CNTLZDCC",
+       "CMPW",
+       "CMPWU",
+       "DIVD",
+       "DIVDCC",
+       "DIVDVCC",
+       "DIVDV",
+       "DIVDU",
+       "DIVDUCC",
+       "DIVDUVCC",
+       "DIVDUV",
+       "EXTSW",
+       "EXTSWCC",
+       "FCFID",
+       "FCFIDCC",
+       "FCTID",
+       "FCTIDCC",
+       "FCTIDZ",
+       "FCTIDZCC",
+       "LDAR",
+       "MOVD",
+       "MOVDU",
+       "MOVWZ",
+       "MOVWZU",
+       "MULHD",
+       "MULHDCC",
+       "MULHDU",
+       "MULHDUCC",
+       "MULLD",
+       "MULLDCC",
+       "MULLDVCC",
+       "MULLDV",
+       "RFID",
+       "RLDMI",
+       "RLDMICC",
+       "RLDC",
+       "RLDCCC",
+       "RLDCR",
+       "RLDCRCC",
+       "RLDCL",
+       "RLDCLCC",
+       "SLBIA",
+       "SLBIE",
+       "SLBMFEE",
+       "SLBMFEV",
+       "SLBMTE",
+       "SLD",
+       "SLDCC",
+       "SRD",
+       "SRAD",
+       "SRADCC",
+       "SRDCC",
+       "STDCCC",
+       "TD",
+       "DWORD",
+       "REMD",
+       "REMDCC",
+       "REMDV",
+       "REMDVCC",
+       "REMDU",
+       "REMDUCC",
+       "REMDUV",
+       "REMDUVCC",
+       "HRFID",
+       "UNDEF",
+       "USEFIELD",
+       "TYPE",
+       "FUNCDATA",
+       "PCDATA",
+       "CHECKNIL",
+       "VARDEF",
+       "VARKILL",
+       "DUFFCOPY",
+       "DUFFZERO",
+       "LAST",
+}
+
+var cnames9 = []string{
+       "NONE",
+       "REG",
+       "FREG",
+       "CREG",
+       "SPR",
+       "ZCON",
+       "SCON",
+       "UCON",
+       "ADDCON",
+       "ANDCON",
+       "LCON",
+       "DCON",
+       "SACON",
+       "SECON",
+       "LACON",
+       "LECON",
+       "DACON",
+       "SBRA",
+       "LBRA",
+       "SAUTO",
+       "LAUTO",
+       "SEXT",
+       "LEXT",
+       "ZOREG",
+       "SOREG",
+       "LOREG",
+       "FPSCR",
+       "MSR",
+       "XER",
+       "LR",
+       "CTR",
+       "ANY",
+       "GOK",
+       "ADDR",
+       "NCLASS",
+}
+
+var dnames9 = []string{
+       D_GOK:    "GOK/R0",
+       D_NONE:   "NONE/XER",
+       D_EXTERN: "EXTERN",
+       D_STATIC: "STATIC",
+       D_AUTO:   "AUTO",
+       D_PARAM:  "PARAM",
+       D_BRANCH: "BRANCH",
+       D_OREG:   "OREG",
+       D_CONST:  "CONST/LR",
+       D_FCONST: "FCONST/CTR",
+       D_SCONST: "SCONST",
+       D_REG:    "REG",
+       D_FPSCR:  "FPSCR",
+       D_MSR:    "MSR",
+       D_FREG:   "FREG",
+       D_CREG:   "CREG",
+       D_SPR:    "SPR",
+       D_OPT:    "OPT",
+       D_FILE:   "FILE",
+       D_FILE1:  "FILE1",
+       D_DCR:    "DCR",
+       D_DCONST: "DCONST",
+       D_ADDR:   "ADDR",
+}
diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go
new file mode 100644 (file)
index 0000000..fe3e626
--- /dev/null
@@ -0,0 +1,3381 @@
+// 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.
+
+package ppc64
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+       "log"
+       "sort"
+)
+
+// Instruction layout.
+
+const (
+       FuncAlign = 8
+)
+
+const (
+       r0iszero = 1
+)
+
+type Optab struct {
+       as    int16
+       a1    uint8
+       a2    uint8
+       a3    uint8
+       a4    uint8
+       type_ int8
+       size  int8
+       param int8
+}
+
+var optab = []Optab{
+       Optab{ATEXT, C_LEXT, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_LEXT, C_REG, C_NONE, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_LEXT, C_NONE, C_LCON, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_LEXT, C_REG, C_LCON, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_ADDR, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_ADDR, C_REG, C_NONE, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_ADDR, C_NONE, C_LCON, C_LCON, 0, 0, 0},
+       Optab{ATEXT, C_ADDR, C_REG, C_LCON, C_LCON, 0, 0, 0},
+       /* move register */
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+       Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+       Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+       Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+       Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+       Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
+       Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
+       Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+       Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+       Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+       Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+       Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+       Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+       Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+       Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+       Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
+       Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+       Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+       Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+       Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+       Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+       Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+       Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+       Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+       Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+       Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+       Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+       Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+       Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+       Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+       Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+       Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
+       Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+       Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
+       Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
+       Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
+       Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+       Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+       Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+       Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+       Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+       Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+       Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
+       Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+       Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
+       Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+       Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
+       Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
+       Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
+       Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
+       Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+       Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+       Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+       Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+       Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+       Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
+       Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
+       Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
+       Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+       Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+       Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
+       Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
+       Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
+       Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
+       Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+       Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+       Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
+       Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
+       Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
+
+       /* store, short offset */
+       Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+
+       /* load, short offset */
+       Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+       Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+       Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+       Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+       Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+       Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+       Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
+       Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+       Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+       Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+       Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+       Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
+       Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+       Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+       Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+
+       /* store, long offset */
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+       Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+       Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+
+       /* load, long offset */
+       Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+       Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+       Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+       Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+       Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
+       Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+       Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+       Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+       Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+       Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
+       Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+       Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+       Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+       Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+       Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
+       Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+       Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+       Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+       Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+       Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
+
+       /* load constant */
+       Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
+       Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+       Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+       Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+       Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+       Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+       Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+       Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+       Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+       Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+       Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+       Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+       Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+       Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+       Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+
+       /* load unsigned/long constants (TO DO: check) */
+       Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+       Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+       Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+       Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+       Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+       Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+       Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+       Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+       Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+       Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+       Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+       Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+       Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+       Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+       Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+       Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+       Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
+       Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
+       Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
+       Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+       Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+       Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+       Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
+       Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
+       Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
+       Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
+       Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+       Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
+       Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
+       Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
+       Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
+       Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
+       Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
+       Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+       Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+       Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+       Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
+       Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+       Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+       Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+       Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
+       Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
+       Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+       Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
+       Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
+       Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
+       Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
+       Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
+       Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+       Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+       Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+       Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+       Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
+       Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
+       Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
+       Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
+       Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
+       Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0},  /* mfmsr */
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0},  /* mtmsrd */
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
+
+       /* 64-bit special registers */
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+       Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+       Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+
+       /* 32-bit special registers (gloss over sign-extension or not?) */
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+       Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+       Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+       Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
+       Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
+       Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+       Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+       Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
+       Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+       Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+       Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+       Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+       Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+       Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
+       Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
+       Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+       Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+       Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
+       Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
+       Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
+       Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
+       Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
+       Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
+       Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
+       Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
+       Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+       Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+       Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+       Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+       Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+       Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+       Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
+       Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+       Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+       Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+       Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
+       Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+       Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
+       Optab{AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
+       Optab{AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+       Optab{APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+       Optab{AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
+       Optab{ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+       Optab{ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+       Optab{ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+
+       Optab{AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+}
+
+type Oprang struct {
+       start []Optab
+       stop  []Optab
+}
+
+var oprange [ALAST]Oprang
+
+var xcmp [C_NCLASS][C_NCLASS]uint8
+
+func span9(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var o *Optab
+       var m int
+       var bflag int
+       var c int64
+       var otxt int64
+       var out [6]uint32
+       var i int32
+       var bp []byte
+
+       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&0xffffffff) + 8
+
+       if oprange[AANDN].start == nil {
+               buildop(ctxt)
+       }
+
+       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 = int(o.size)
+               if m == 0 {
+                       if p.As != ANOP && p.As != AFUNCDATA && p.As != APCDATA {
+                               ctxt.Diag("zero-width instruction\n%v", p)
+                       }
+                       continue
+               }
+
+               c += int64(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
+
+       for bflag != 0 {
+               if ctxt.Debugvlog != 0 {
+                       fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.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 != nil {
+
+                               otxt = p.Pcond.Pc - c
+                               if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
+                                       q = ctxt.NewProg()
+                                       q.Link = p.Link
+                                       p.Link = q
+                                       q.As = ABR
+                                       q.To.Type = D_BRANCH
+                                       q.Pcond = p.Pcond
+                                       p.Pcond = q
+                                       q = ctxt.NewProg()
+                                       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 = int(o.size)
+                       if m == 0 {
+                               if p.As != ANOP && p.As != AFUNCDATA && p.As != APCDATA {
+                                       ctxt.Diag("zero-width instruction\n%v", p)
+                               }
+                               continue
+                       }
+
+                       c += int64(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 = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+       }
+
+       obj.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 int(o.size) > 4*len(out) {
+                       log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
+               }
+               asmout(ctxt, p, o, out[:])
+               for i = 0; i < int32(o.size/4); i++ {
+                       ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
+                       bp = bp[4:]
+               }
+       }
+}
+
+func isint32(v int64) int {
+       return bool2int(int64(int32(v)) == v)
+}
+
+func isuint32(v uint64) int {
+       return bool2int(uint64(uint32(v)) == v)
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+       var s *obj.LSym
+
+       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,
+                       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 = int64(ctxt.Autosize) + a.Offset
+                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                               return C_SAUTO
+                       }
+                       return C_LAUTO
+
+               case D_PARAM:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+                       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 & 31
+               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
+                               }
+                               if isint32(ctxt.Instoffset) != 0 {
+                                       return C_LACON
+                               }
+                               return C_DACON
+                       }
+
+                       goto consize
+
+               case D_EXTERN,
+                       D_STATIC:
+                       s = a.Sym
+                       if s == nil {
+                               break
+                       }
+                       if s.Type == obj.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 = int64(ctxt.Autosize) + a.Offset
+                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                               return C_SACON
+                       }
+                       return C_LACON
+
+               case D_PARAM:
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+                       if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+                               return C_SACON
+                       }
+                       return C_LACON
+               }
+
+               return C_GOK
+
+       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(uint64(ctxt.Instoffset)) != 0 { /* && (instoffset & (1<<31)) == 0) */
+                               return C_UCON
+                       }
+                       if isint32(ctxt.Instoffset) != 0 || isuint32(uint64(ctxt.Instoffset)) != 0 {
+                               return C_LCON
+                       }
+                       return C_DCON
+               }
+
+               if ctxt.Instoffset >= -0x8000 {
+                       return C_ADDCON
+               }
+               if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) != 0 {
+                       return C_UCON
+               }
+               if isint32(ctxt.Instoffset) != 0 {
+                       return C_LCON
+               }
+               return C_DCON
+
+       case D_BRANCH:
+               return C_SBRA
+       }
+
+       return C_GOK
+}
+
+func prasm(p *obj.Prog) {
+       fmt.Printf("%v\n", p)
+}
+
+func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+       var a1 int
+       var a2 int
+       var a3 int
+       var a4 int
+       var r int
+       var c1 []byte
+       var c3 []byte
+       var c4 []byte
+       var o []Optab
+       var e []Optab
+
+       a1 = int(p.Optab)
+       if a1 != 0 {
+               return &optab[a1-1:][0]
+       }
+       a1 = int(p.From.Class)
+       if a1 == 0 {
+               a1 = aclass(ctxt, &p.From) + 1
+               p.From.Class = int8(a1)
+       }
+
+       a1--
+       a3 = int(p.From3.Class)
+       if a3 == 0 {
+               a3 = aclass(ctxt, &p.From3) + 1
+               p.From3.Class = int8(a3)
+       }
+
+       a3--
+       a4 = int(p.To.Class)
+       if a4 == 0 {
+               a4 = aclass(ctxt, &p.To) + 1
+               p.To.Class = int8(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 = int(p.As)
+
+       o = oprange[r].start
+       if o == nil {
+               o = oprange[r].stop /* just generate an error */
+       }
+       e = oprange[r].stop
+       c1 = xcmp[a1][:]
+       c3 = xcmp[a3][:]
+       c4 = xcmp[a4][:]
+       for ; -cap(o) < -cap(e); o = o[1:] {
+               if int(o[0].a2) == a2 {
+                       if c1[o[0].a1] != 0 {
+                               if c3[o[0].a3] != 0 {
+                                       if c4[o[0].a4] != 0 {
+                                               p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+                                               return &o[0]
+                                       }
+                               }
+                       }
+               }
+       }
+
+       ctxt.Diag("illegal combination %v %v %v %v %v", Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
+       prasm(p)
+       if o == nil {
+               o = optab
+       }
+       return &o[0]
+}
+
+func cmp(a int, b int) bool {
+       if a == b {
+               return true
+       }
+       switch a {
+       case C_LCON:
+               if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
+                       return true
+               }
+
+       case C_ADDCON:
+               if b == C_ZCON || b == C_SCON {
+                       return true
+               }
+
+       case C_ANDCON:
+               if b == C_ZCON || b == C_SCON {
+                       return true
+               }
+
+       case C_SPR:
+               if b == C_LR || b == C_XER || b == C_CTR {
+                       return true
+               }
+
+       case C_UCON:
+               if b == C_ZCON {
+                       return true
+               }
+
+       case C_SCON:
+               if b == C_ZCON {
+                       return true
+               }
+
+       case C_LACON:
+               if b == C_SACON {
+                       return true
+               }
+
+       case C_LBRA:
+               if b == C_SBRA {
+                       return true
+               }
+
+       case C_LEXT:
+               if b == C_SEXT {
+                       return true
+               }
+
+       case C_LAUTO:
+               if b == C_SAUTO {
+                       return true
+               }
+
+       case C_REG:
+               if b == C_ZCON {
+                       return r0iszero != 0 /*TypeKind(100016)*/
+               }
+
+       case C_LOREG:
+               if b == C_ZOREG || b == C_SOREG {
+                       return true
+               }
+
+       case C_SOREG:
+               if b == C_ZOREG {
+                       return true
+               }
+
+       case C_ANY:
+               return true
+       }
+
+       return false
+}
+
+type ocmp []Optab
+
+func (x ocmp) Len() int {
+       return len(x)
+}
+
+func (x ocmp) Swap(i, j int) {
+       x[i], x[j] = x[j], x[i]
+}
+
+func (x ocmp) Less(i, j int) bool {
+       var p1 *Optab
+       var p2 *Optab
+       var n int
+
+       p1 = &x[i]
+       p2 = &x[j]
+       n = int(p1.as) - int(p2.as)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a1) - int(p2.a1)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a2) - int(p2.a2)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a3) - int(p2.a3)
+       if n != 0 {
+               return n < 0
+       }
+       n = int(p1.a4) - int(p2.a4)
+       if n != 0 {
+               return n < 0
+       }
+       return false
+}
+
+func buildop(ctxt *obj.Link) {
+       var i int
+       var n int
+       var r int
+
+       for i = 0; i < C_NCLASS; i++ {
+               for n = 0; n < C_NCLASS; n++ {
+                       if cmp(n, i) {
+                               xcmp[i][n] = 1
+                       }
+               }
+       }
+       for n = 0; optab[n].as != AXXX; n++ {
+
+       }
+       sort.Sort(ocmp(optab[:n]))
+       for i = 0; i < n; i++ {
+               r = int(optab[i].as)
+               oprange[r].start = optab[i:]
+               for int(optab[i].as) == r {
+                       i++
+               }
+               oprange[r].stop = optab[i:]
+               i--
+
+               switch r {
+               default:
+                       ctxt.Diag("unknown op in build: %v", Aconv(r))
+                       log.Fatalf("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]
+
+               case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
+                       oprange[ASTWCCC] = oprange[r]
+
+                       oprange[ASTDCCC] = oprange[r]
+
+               case AREM: /* macro */
+                       oprange[AREMCC] = oprange[r]
+
+                       oprange[AREMV] = oprange[r]
+                       oprange[AREMVCC] = oprange[r]
+
+               case AREMU:
+                       oprange[AREMU] = oprange[r]
+                       oprange[AREMUCC] = oprange[r]
+                       oprange[AREMUV] = oprange[r]
+                       oprange[AREMUVCC] = oprange[r]
+
+               case AREMD:
+                       oprange[AREMDCC] = oprange[r]
+                       oprange[AREMDV] = oprange[r]
+                       oprange[AREMDVCC] = oprange[r]
+
+               case AREMDU:
+                       oprange[AREMDU] = oprange[r]
+                       oprange[AREMDUCC] = oprange[r]
+                       oprange[AREMDUV] = oprange[r]
+                       oprange[AREMDUVCC] = oprange[r]
+
+               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]
+
+               case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
+                       oprange[AMOVH] = oprange[r]
+
+                       oprange[AMOVHZ] = oprange[r]
+
+               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]
+
+               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]
+
+               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]
+
+               case AADDC:
+                       oprange[AADDCCC] = oprange[r]
+
+               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]
+
+               case ABR:
+                       oprange[ABL] = oprange[r]
+
+               case ABC:
+                       oprange[ABCL] = oprange[r]
+
+               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]
+
+               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]
+
+               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]
+
+               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]
+
+               case AFMUL:
+                       oprange[AFMULS] = oprange[r]
+                       oprange[AFMULCC] = oprange[r]
+                       oprange[AFMULSCC] = oprange[r]
+
+               case AFCMPO:
+                       oprange[AFCMPU] = oprange[r]
+
+               case AMTFSB0:
+                       oprange[AMTFSB0CC] = oprange[r]
+                       oprange[AMTFSB1] = oprange[r]
+                       oprange[AMTFSB1CC] = oprange[r]
+
+               case ANEG: /* op [Ra,] Rd */
+                       oprange[ANEGCC] = oprange[r]
+
+                       oprange[ANEGV] = oprange[r]
+                       oprange[ANEGVCC] = oprange[r]
+
+               case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
+                       oprange[AXOR] = oprange[r]
+
+               case ASLW:
+                       oprange[ASLWCC] = oprange[r]
+                       oprange[ASRW] = oprange[r]
+                       oprange[ASRWCC] = oprange[r]
+
+               case ASLD:
+                       oprange[ASLDCC] = oprange[r]
+                       oprange[ASRD] = oprange[r]
+                       oprange[ASRDCC] = oprange[r]
+
+               case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+                       oprange[ASRAWCC] = oprange[r]
+
+               case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+                       oprange[ASRADCC] = oprange[r]
+
+               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]
+
+               case ASYNC:
+                       oprange[AISYNC] = oprange[r]
+                       oprange[APTESYNC] = oprange[r]
+                       oprange[ATLBSYNC] = oprange[r]
+
+               case ARLWMI:
+                       oprange[ARLWMICC] = oprange[r]
+                       oprange[ARLWNM] = oprange[r]
+                       oprange[ARLWNMCC] = oprange[r]
+
+               case ARLDMI:
+                       oprange[ARLDMICC] = oprange[r]
+
+               case ARLDC:
+                       oprange[ARLDCCC] = oprange[r]
+
+               case ARLDCL:
+                       oprange[ARLDCR] = oprange[r]
+                       oprange[ARLDCLCC] = oprange[r]
+                       oprange[ARLDCRCC] = oprange[r]
+
+               case AFMOVD:
+                       oprange[AFMOVDCC] = oprange[r]
+                       oprange[AFMOVDU] = oprange[r]
+                       oprange[AFMOVS] = oprange[r]
+                       oprange[AFMOVSU] = oprange[r]
+
+               case AECIWX:
+                       oprange[ALWAR] = oprange[r]
+                       oprange[ALDAR] = oprange[r]
+
+               case ASYSCALL: /* just the op; flow of control */
+                       oprange[ARFI] = oprange[r]
+
+                       oprange[ARFCI] = oprange[r]
+                       oprange[ARFID] = oprange[r]
+                       oprange[AHRFID] = oprange[r]
+
+               case AMOVHBR:
+                       oprange[AMOVWBR] = oprange[r]
+
+               case ASLBMFEE:
+                       oprange[ASLBMFEV] = oprange[r]
+
+               case ATW:
+                       oprange[ATD] = oprange[r]
+
+               case ATLBIE:
+                       oprange[ASLBIE] = oprange[r]
+                       oprange[ATLBIEL] = oprange[r]
+
+               case AEIEIO:
+                       oprange[ASLBIA] = oprange[r]
+
+               case ACMP:
+                       oprange[ACMPW] = oprange[r]
+
+               case ACMPU:
+                       oprange[ACMPWU] = oprange[r]
+
+               case AADD,
+                       AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
+                       ALSW,
+                       AMOVW,
+                       /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
+                       AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals  */
+                       AMOVD,  /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
+                       AMOVB,  /* macro: move byte with sign extension */
+                       AMOVBU, /* macro: move byte with sign extension & update */
+                       AMOVFL,
+                       AMULLW,
+                       /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
+                       ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */
+                       ASTSW,
+                       ASLBMTE,
+                       AWORD,
+                       ADWORD,
+                       ANOP,
+                       ATEXT,
+                       AUNDEF,
+                       AUSEFIELD,
+                       AFUNCDATA,
+                       APCDATA,
+                       ADUFFZERO,
+                       ADUFFCOPY:
+                       break
+               }
+       }
+}
+
+func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
+       return o<<26 | xo<<1 | oe<<10 | rc&1
+}
+
+func OPCC(o uint32, xo uint32, rc uint32) uint32 {
+       return OPVCC(o, xo, 0, rc)
+}
+
+func OP(o uint32, xo uint32) uint32 {
+       return OPVCC(o, xo, 0, 0)
+}
+
+/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
+func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 {
+
+       return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11
+}
+
+func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
+       return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
+}
+
+func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
+       return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
+}
+
+func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
+       return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
+}
+
+func OP_BR(op uint32, li uint32, aa uint32) uint32 {
+       return op | li&0x03FFFFFC | aa<<1
+}
+
+func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 {
+       return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1
+}
+
+func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
+       return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
+}
+
+func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 {
+       return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1
+}
+
+const (
+       OP_ADD    = 31<<26 | 266<<1 | 0<<10 | 0
+       OP_ADDI   = 14<<26 | 0<<1 | 0<<10 | 0
+       OP_ADDIS  = 15<<26 | 0<<1 | 0<<10 | 0
+       OP_ANDI   = 28<<26 | 0<<1 | 0<<10 | 0
+       OP_EXTSB  = 31<<26 | 954<<1 | 0<<10 | 0
+       OP_EXTSH  = 31<<26 | 922<<1 | 0<<10 | 0
+       OP_EXTSW  = 31<<26 | 986<<1 | 0<<10 | 0
+       OP_MCRF   = 19<<26 | 0<<1 | 0<<10 | 0
+       OP_MCRFS  = 63<<26 | 64<<1 | 0<<10 | 0
+       OP_MCRXR  = 31<<26 | 512<<1 | 0<<10 | 0
+       OP_MFCR   = 31<<26 | 19<<1 | 0<<10 | 0
+       OP_MFFS   = 63<<26 | 583<<1 | 0<<10 | 0
+       OP_MFMSR  = 31<<26 | 83<<1 | 0<<10 | 0
+       OP_MFSPR  = 31<<26 | 339<<1 | 0<<10 | 0
+       OP_MFSR   = 31<<26 | 595<<1 | 0<<10 | 0
+       OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0
+       OP_MTCRF  = 31<<26 | 144<<1 | 0<<10 | 0
+       OP_MTFSF  = 63<<26 | 711<<1 | 0<<10 | 0
+       OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0
+       OP_MTMSR  = 31<<26 | 146<<1 | 0<<10 | 0
+       OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0
+       OP_MTSPR  = 31<<26 | 467<<1 | 0<<10 | 0
+       OP_MTSR   = 31<<26 | 210<<1 | 0<<10 | 0
+       OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0
+       OP_MULLW  = 31<<26 | 235<<1 | 0<<10 | 0
+       OP_MULLD  = 31<<26 | 233<<1 | 0<<10 | 0
+       OP_OR     = 31<<26 | 444<<1 | 0<<10 | 0
+       OP_ORI    = 24<<26 | 0<<1 | 0<<10 | 0
+       OP_ORIS   = 25<<26 | 0<<1 | 0<<10 | 0
+       OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0
+       OP_SUBF   = 31<<26 | 40<<1 | 0<<10 | 0
+       OP_RLDIC  = 30<<26 | 4<<1 | 0<<10 | 0
+       OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0
+       OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0
+)
+
+func oclass(a *obj.Addr) int {
+       return int(a.Class) - 1
+}
+
+// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
+func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
+
+       var rel *obj.Reloc
+
+       rel = obj.Addrel(ctxt.Cursym)
+       rel.Off = int32(ctxt.Pc)
+       rel.Siz = 8
+       rel.Sym = s
+       rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
+       rel.Type = obj.R_ADDRPOWER
+}
+
+/*
+ * 32-bit masks
+ */
+func getmask(m []byte, v uint32) int {
+
+       var i int
+
+       m[1] = 0
+       m[0] = m[1]
+       if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
+               if getmask(m, ^v) != 0 {
+                       i = int(m[0])
+                       m[0] = m[1] + 1
+                       m[1] = byte(i - 1)
+                       return 1
+               }
+
+               return 0
+       }
+
+       for i = 0; i < 32; i++ {
+               if v&(1<<uint(31-i)) != 0 {
+                       m[0] = byte(i)
+                       for {
+                               m[1] = byte(i)
+                               i++
+                               if !(i < 32 && v&(1<<uint(31-i)) != 0) {
+                                       break
+                               }
+                       }
+
+                       for ; i < 32; i++ {
+                               if v&(1<<uint(31-i)) != 0 {
+                                       return 0
+                               }
+                       }
+                       return 1
+               }
+       }
+
+       return 0
+}
+
+func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
+       if !(getmask(m, v) != 0) {
+               ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+       }
+}
+
+/*
+ * 64-bit masks (rldic etc)
+ */
+func getmask64(m []byte, v uint64) int {
+
+       var i int
+
+       m[1] = 0
+       m[0] = m[1]
+       for i = 0; i < 64; i++ {
+               if v&(uint64(1)<<uint(63-i)) != 0 {
+                       m[0] = byte(i)
+                       for {
+                               m[1] = byte(i)
+                               i++
+                               if !(i < 64 && v&(uint64(1)<<uint(63-i)) != 0) {
+                                       break
+                               }
+                       }
+
+                       for ; i < 64; i++ {
+                               if v&(uint64(1)<<uint(63-i)) != 0 {
+                                       return 0
+                               }
+                       }
+                       return 1
+               }
+       }
+
+       return 0
+}
+
+func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
+       if !(getmask64(m, v) != 0) {
+               ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+       }
+}
+
+func loadu32(r int, d int64) uint32 {
+       var v int32
+
+       v = int32(d >> 16)
+       if isuint32(uint64(d)) != 0 {
+               return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v))
+       }
+       return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v))
+}
+
+func high16adjusted(d int32) uint16 {
+       if d&0x8000 != 0 {
+               return uint16((d >> 16) + 1)
+       }
+       return uint16(d >> 16)
+}
+
+func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
+       var o1 uint32
+       var o2 uint32
+       var o3 uint32
+       var o4 uint32
+       var o5 uint32
+       var v int32
+       var t int32
+       var d int64
+       var r int
+       var a int
+       var mask [2]uint8
+       var rel *obj.Reloc
+
+       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)
+
+       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 != 0 /*TypeKind(100016)*/ && v != 0 {
+                               //nerrors--;
+                               ctxt.Diag("literal operation on R0\n%v", p)
+                       }
+
+                       o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
+                       break
+               }
+
+               o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg))
+
+       case 2: /* int/cr/fp op Rb,[Ra],Rd */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+       case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
+               d = vregoff(ctxt, &p.From)
+
+               v = int32(d)
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) {
+                       ctxt.Diag("literal operation on R0\n%v", p)
+               }
+               a = OP_ADDI
+               if o.a1 == C_UCON {
+                       if d&0xffff != 0 {
+                               log.Fatalf("invalid handling of %v", p)
+                       }
+                       v >>= 16
+                       if r == REGZERO && isuint32(uint64(d)) != 0 {
+                               o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
+                               break
+                       }
+
+                       a = OP_ADDIS
+               } else {
+
+                       if int64(int16(d)) != d {
+                               log.Fatalf("invalid handling of %v", p)
+                       }
+               }
+
+               o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
+
+       case 4: /* add/mul $scon,[r1],r2 */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 {
+                       ctxt.Diag("literal operation on R0\n%v", p)
+               }
+               if int32(int16(v)) != v {
+                       log.Fatalf("mishandled instruction %v", p)
+               }
+               o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+       case 5: /* syscall */
+               o1 = uint32(oprrr(ctxt, int(p.As)))
+
+       case 6: /* logical op Rb,[Rs,]Ra; no literal */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+       case 7: /* mov r, soreg ==> stw o(r) */
+               r = int(p.To.Reg)
+
+               if r == NREG {
+                       r = int(o.param)
+               }
+               v = regoff(ctxt, &p.To)
+               if p.To.Type == D_OREG && p.Reg != NREG {
+                       if v != 0 {
+                               ctxt.Diag("illegal indexed instruction\n%v", p)
+                       }
+                       o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.Reg), uint32(r))
+               } else {
+
+                       if int32(int16(v)) != v {
+                               log.Fatalf("mishandled instruction %v", p)
+                       }
+                       o1 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(v))
+               }
+
+       case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
+               r = int(p.From.Reg)
+
+               if r == NREG {
+                       r = int(o.param)
+               }
+               v = regoff(ctxt, &p.From)
+               if p.From.Type == D_OREG && p.Reg != NREG {
+                       if v != 0 {
+                               ctxt.Diag("illegal indexed instruction\n%v", p)
+                       }
+                       o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
+               } else {
+
+                       if int32(int16(v)) != v {
+                               log.Fatalf("mishandled instruction %v", p)
+                       }
+                       o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+               }
+
+       case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
+               r = int(p.From.Reg)
+
+               if r == NREG {
+                       r = int(o.param)
+               }
+               v = regoff(ctxt, &p.From)
+               if p.From.Type == D_OREG && p.Reg != NREG {
+                       if v != 0 {
+                               ctxt.Diag("illegal indexed instruction\n%v", p)
+                       }
+                       o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
+               } else {
+
+                       o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+               }
+               o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+
+       case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r))
+
+       case 11: /* br/bl lbra */
+               v = 0
+
+               if p.Pcond != nil {
+                       v = int32(p.Pcond.Pc - p.Pc)
+                       if v&03 != 0 {
+                               ctxt.Diag("odd branch target address\n%v", p)
+                               v &^= 03
+                       }
+
+                       if v < -(1<<25) || v >= 1<<24 {
+                               ctxt.Diag("branch too far\n%v", p)
+                       }
+               }
+
+               o1 = OP_BR(uint32(opirr(ctxt, int(p.As))), uint32(v), 0)
+               if p.To.Sym != nil {
+                       rel = obj.Addrel(ctxt.Cursym)
+                       rel.Off = int32(ctxt.Pc)
+                       rel.Siz = 4
+                       rel.Sym = p.To.Sym
+                       v += int32(p.To.Offset)
+                       if v&03 != 0 {
+                               ctxt.Diag("odd branch target address\n%v", p)
+                               v &^= 03
+                       }
+
+                       rel.Add = int64(v)
+                       rel.Type = obj.R_CALLPOWER
+               }
+
+       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 != 0 /*TypeKind(100016)*/ && v != 0 {
+                               ctxt.Diag("literal operation on R0\n%v", p)
+                       }
+
+                       o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
+                       break
+               }
+
+               if p.As == AMOVW {
+                       o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+               } else {
+
+                       o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+               }
+
+       case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
+               if p.As == AMOVBZ {
+
+                       o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31)
+               } else if p.As == AMOVH {
+                       o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+               } else if p.As == AMOVHZ {
+                       o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31)
+               } else if p.As == AMOVWZ {
+                       o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */
+               } else {
+
+                       ctxt.Diag("internal: bad mov[bhw]z\n%v", p)
+               }
+
+       case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               d = vregoff(ctxt, &p.From3)
+               maskgen64(ctxt, p, mask[:], uint64(d))
+               switch p.As {
+               case ARLDCL,
+                       ARLDCLCC:
+                       a = int(mask[0]) /* MB */
+                       if mask[1] != 63 {
+                               ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
+                       }
+
+               case ARLDCR,
+                       ARLDCRCC:
+                       a = int(mask[1]) /* ME */
+                       if mask[0] != 0 {
+                               ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
+                       }
+
+               default:
+                       ctxt.Diag("unexpected op in rldc case\n%v", p)
+                       a = 0
+               }
+
+               o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+               o1 |= (uint32(a) & 31) << 6
+               if a&0x20 != 0 {
+                       o1 |= 1 << 5 /* mb[5] is top bit */
+               }
+
+       case 17, /* bc bo,bi,lbra (same for now) */
+               16: /* bc bo,bi,sbra */
+               a = 0
+
+               if p.From.Type == D_CONST {
+                       a = int(regoff(ctxt, &p.From))
+               }
+               r = int(p.Reg)
+               if r == NREG {
+                       r = 0
+               }
+               v = 0
+               if p.Pcond != nil {
+                       v = int32(p.Pcond.Pc - p.Pc)
+               }
+               if v&03 != 0 {
+                       ctxt.Diag("odd branch target address\n%v", p)
+                       v &^= 03
+               }
+
+               if v < -(1<<16) || v >= 1<<15 {
+                       ctxt.Diag("branch too far\n%v", p)
+               }
+               o1 = OP_BC(uint32(opirr(ctxt, int(p.As))), uint32(a), uint32(r), uint32(v), 0)
+
+       case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
+               if p.As == ABC || p.As == ABCL {
+
+                       v = regoff(ctxt, &p.To) & 31
+               } else {
+
+                       v = 20 /* unconditional */
+               }
+               r = int(p.Reg)
+               if r == NREG {
+                       r = 0
+               }
+               o1 = AOP_RRR(OP_MTSPR, uint32(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, uint32(v), uint32(r))
+
+       case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
+               if p.As == ABC || p.As == ABCL {
+
+                       v = regoff(ctxt, &p.From) & 31
+               } else {
+
+                       v = 20 /* unconditional */
+               }
+               r = int(p.Reg)
+               if r == NREG {
+                       r = 0
+               }
+               switch oclass(&p.To) {
+               case C_CTR:
+                       o1 = OPVCC(19, 528, 0, 0)
+
+               case C_LR:
+                       o1 = OPVCC(19, 16, 0, 0)
+
+               default:
+                       ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p)
+                       v = 0
+               }
+
+               if p.As == ABL || p.As == ABCL {
+                       o1 |= 1
+               }
+               o1 = OP_BCR(o1, uint32(v), uint32(r))
+
+       case 19: /* mov $lcon,r ==> cau+or */
+               d = vregoff(ctxt, &p.From)
+
+               if p.From.Sym == nil {
+                       o1 = loadu32(int(p.To.Reg), d)
+                       o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
+               } else {
+
+                       o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
+                       o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
+                       addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+               }
+
+       //if(dlm) reloc(&p->from, p->pc, 0);
+
+       case 20: /* add $ucon,,r */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               if p.As == AADD && (!(r0iszero != 0 /*TypeKind(100016)*/) && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
+                       ctxt.Diag("literal operation on R0\n%v", p)
+               }
+               o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As)+AEND)), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
+
+       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%v", p)
+               }
+               d = vregoff(ctxt, &p.From)
+               o1 = loadu32(REGTMP, d)
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
+               if p.From.Sym != nil {
+                       ctxt.Diag("%v is not supported", p)
+               }
+
+       //if(dlm) reloc(&p->from, p->pc, 0);
+
+       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%v", p)
+               }
+               d = vregoff(ctxt, &p.From)
+               o1 = loadu32(REGTMP, d)
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o3 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
+               if p.From.Sym != nil {
+                       ctxt.Diag("%v is not supported", p)
+               }
+
+               //if(dlm) reloc(&p->from, p->pc, 0);
+
+               /*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 = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               switch p.As {
+               case ASLD,
+                       ASLDCC:
+                       a = int(63 - v)
+                       o1 = OP_RLDICR
+
+               case ASRD,
+                       ASRDCC:
+                       a = int(v)
+                       v = 64 - v
+                       o1 = OP_RLDICL
+
+               default:
+                       ctxt.Diag("unexpected op in sldi case\n%v", p)
+                       a = 0
+                       o1 = 0
+               }
+
+               o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F))
+               o1 |= (uint32(a) & 31) << 6
+               if v&0x20 != 0 {
+                       o1 |= 1 << 1
+               }
+               if a&0x20 != 0 {
+                       o1 |= 1 << 5 /* mb[5] is top bit */
+               }
+               if p.As == ASLDCC || p.As == ASRDCC {
+                       o1 |= 1 /* Rc */
+               }
+
+       case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
+               if p.To.Reg == REGTMP {
+
+                       ctxt.Diag("can't synthesize large constant\n%v", p)
+               }
+               v = regoff(ctxt, &p.From)
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+               o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
+
+       case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
+               v = regoff(ctxt, &p.From3)
+
+               r = int(p.From.Reg)
+               o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+       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%v", p)
+               }
+               v = regoff(ctxt, &p.From3)
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
+               o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
+               if p.From.Sym != nil {
+                       ctxt.Diag("%v is not supported", p)
+               }
+
+       //if(dlm) reloc(&p->from3, p->pc, 0);
+
+       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[:], uint64(d))
+               switch p.As {
+               case ARLDC,
+                       ARLDCCC:
+                       a = int(mask[0]) /* MB */
+                       if int32(mask[1]) != (63 - v) {
+                               ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+                       }
+
+               case ARLDCL,
+                       ARLDCLCC:
+                       a = int(mask[0]) /* MB */
+                       if mask[1] != 63 {
+                               ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+                       }
+
+               case ARLDCR,
+                       ARLDCRCC:
+                       a = int(mask[1]) /* ME */
+                       if mask[0] != 0 {
+                               ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+                       }
+
+               default:
+                       ctxt.Diag("unexpected op in rldic case\n%v", p)
+                       a = 0
+               }
+
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
+               o1 |= (uint32(a) & 31) << 6
+               if v&0x20 != 0 {
+                       o1 |= 1 << 1
+               }
+               if a&0x20 != 0 {
+                       o1 |= 1 << 5 /* mb[5] is top bit */
+               }
+
+       case 30: /* rldimi $sh,s,$mask,a */
+               v = regoff(ctxt, &p.From)
+
+               d = vregoff(ctxt, &p.From3)
+               maskgen64(ctxt, p, mask[:], uint64(d))
+               if int32(mask[1]) != (63 - v) {
+                       ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+               }
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
+               o1 |= (uint32(mask[0]) & 31) << 6
+               if v&0x20 != 0 {
+                       o1 |= 1 << 1
+               }
+               if mask[0]&0x20 != 0 {
+                       o1 |= 1 << 5 /* mb[5] is top bit */
+               }
+
+       case 31: /* dword */
+               d = vregoff(ctxt, &p.From)
+
+               if ctxt.Arch.Endian == obj.BigEndian {
+                       o1 = uint32(d >> 32)
+                       o2 = uint32(d)
+               } else {
+
+                       o1 = uint32(d)
+                       o2 = uint32(d >> 32)
+               }
+
+               if p.From.Sym != nil {
+                       rel = obj.Addrel(ctxt.Cursym)
+                       rel.Off = int32(ctxt.Pc)
+                       rel.Siz = 8
+                       rel.Sym = p.From.Sym
+                       rel.Add = p.From.Offset
+                       rel.Type = obj.R_ADDR
+                       o2 = 0
+                       o1 = o2
+               }
+
+       case 32: /* fmul frc,fra,frd */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6
+
+       case 33: /* fabs [frb,]frd; fmr. frb,frd */
+               r = int(p.From.Reg)
+
+               if oclass(&p.From) == C_NONE {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r))
+
+       case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
+
+       case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
+               v = regoff(ctxt, &p.To)
+
+               r = int(p.To.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
+
+       case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+
+       case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.From.Reg)
+               if r == NREG {
+                       r = int(o.param)
+               }
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+               o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+
+       case 40: /* word */
+               o1 = uint32(regoff(ctxt, &p.From))
+
+       case 41: /* stswi */
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
+
+       case 42: /* lswi */
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
+
+       case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = 0
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(r), uint32(p.From.Reg))
+
+       case 44: /* indexed store */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = 0
+               }
+               o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
+
+       case 45: /* indexed load */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = 0
+               }
+               o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+       case 46: /* plain op */
+               o1 = uint32(oprrr(ctxt, int(p.As)))
+
+       case 47: /* op Ra, Rd; also op [Ra,] Rd */
+               r = int(p.From.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+
+       case 48: /* op Rs, Ra */
+               r = int(p.From.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+
+       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(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21
+               } else {
+
+                       o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.From.Reg))
+               }
+
+       case 50: /* rem[u] r1[,r2],r3 */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               v = oprrr(ctxt, int(p.As))
+               t = v & (1<<10 | 1) /* OE|Rc */
+               o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
+               o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg))
+               o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
+               if p.As == AREMU {
+                       o4 = o3
+
+                       /* Clear top 32 bits */
+                       o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5
+               }
+
+       case 51: /* remd[u] r1[,r2],r3 */
+               r = int(p.Reg)
+
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               v = oprrr(ctxt, int(p.As))
+               t = v & (1<<10 | 1) /* OE|Rc */
+               o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
+               o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg))
+               o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
+
+       case 52: /* mtfsbNx cr(n) */
+               v = regoff(ctxt, &p.From) & 31
+
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(v), 0, 0)
+
+       case 53: /* mffsX ,fr1 */
+               o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0)
+
+       case 54: /* mov msr,r1; mov r1, msr*/
+               if oclass(&p.From) == C_REG {
+
+                       if p.As == AMOVD {
+                               o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0)
+                       } else {
+
+                               o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0)
+                       }
+               } else {
+
+                       o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0)
+               }
+
+       case 55: /* op Rb, Rd */
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(p.From.Reg))
+
+       case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31)
+               if p.As == ASRAD && (v&0x20 != 0) {
+                       o1 |= 1 << 1 /* mb[5] */
+               }
+
+       case 57: /* slw $sh,[s,]a -> rlwinm ... */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(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] = uint8(v)
+                       mask[1] = 31
+                       v = 32 - v
+               } else {
+
+                       mask[0] = 0
+                       mask[1] = uint8(31 - v)
+               }
+
+               o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1]))
+               if p.As == ASLWCC || p.As == ASRWCC {
+                       o1 |= 1 /* Rc */
+               }
+
+       case 58: /* logical $andcon,[s],a */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+       case 59: /* or/and $ucon,,r */
+               v = regoff(ctxt, &p.From)
+
+               r = int(p.Reg)
+               if r == NREG {
+                       r = int(p.To.Reg)
+               }
+               o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+AEND)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */
+
+       case 60: /* tw to,a,b */
+               r = int(regoff(ctxt, &p.From) & 31)
+
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
+
+       case 61: /* tw to,a,$simm */
+               r = int(regoff(ctxt, &p.From) & 31)
+
+               v = regoff(ctxt, &p.To)
+               o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(v))
+
+       case 62: /* rlwmi $sh,s,$mask,a */
+               v = regoff(ctxt, &p.From)
+
+               maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
+               o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
+
+       case 63: /* rlwmi b,s,$mask,a */
+               maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
+
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
+               o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
+
+       case 64: /* mtfsf fr[, $m] {,fpcsr} */
+               if p.From3.Type != D_NONE {
+
+                       v = regoff(ctxt, &p.From3) & 255
+               } else {
+
+                       v = 255
+               }
+               o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11
+
+       case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
+               if p.To.Reg == NREG {
+
+                       ctxt.Diag("must specify FPSCR(n)\n%v", p)
+               }
+               o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12
+
+       case 66: /* mov spr,r1; mov r1,spr, also dcr */
+               if p.From.Type == D_REG {
+
+                       r = int(p.From.Reg)
+                       v = int32(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 = int(p.To.Reg)
+                       v = int32(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, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11
+
+       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%v", p)
+               }
+               o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
+
+       case 68: /* mfcr rD; mfocrf CRM,rD */
+               if p.From.Type == D_CREG && p.From.Reg != NREG {
+
+                       v = 1 << uint(7-(p.To.Reg&7))                                         /* CR(n) */
+                       o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */
+               } else {
+
+                       o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */
+               }
+
+       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%v", p)
+                       }
+                       v = regoff(ctxt, &p.From3) & 0xff
+               } else {
+
+                       if p.To.Reg == NREG {
+                               v = 0xff /* CR */
+                       } else {
+
+                               v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
+                       }
+               }
+
+               o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12
+
+       case 70: /* [f]cmp r,r,cr*/
+               if p.Reg == NREG {
+
+                       r = 0
+               } else {
+
+                       r = (int(p.Reg) & 7) << 2
+               }
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
+
+       case 71: /* cmp[l] r,i,cr*/
+               if p.Reg == NREG {
+
+                       r = 0
+               } else {
+
+                       r = (int(p.Reg) & 7) << 2
+               }
+               o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff
+
+       case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
+               o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.From.Reg), 0, uint32(p.To.Reg))
+
+       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%v", p)
+               }
+               o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
+
+       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: %v", p)
+                       }
+                       o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset))
+               } else if p.From.Type == D_REG {
+                       o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg))
+               } else {
+
+                       ctxt.Diag("illegal syscall: %v", p)
+                       o1 = 0x7fe00008 // trap always
+               }
+
+               o2 = uint32(oprrr(ctxt, int(p.As)))
+               o3 = AOP_RRR(uint32(oprrr(ctxt, AXOR)), REGZERO, REGZERO, REGZERO) // XOR R0, R0
+
+       case 78: /* undef */
+               o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
+                  always to be an illegal instruction."  */
+
+               /* relocation operations */
+       case 74:
+               v = regoff(ctxt, &p.To)
+
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
+               addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
+
+       //if(dlm) reloc(&p->to, p->pc, 1);
+
+       case 75:
+               v = regoff(ctxt, &p.From)
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+               addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+
+       //if(dlm) reloc(&p->from, p->pc, 1);
+
+       case 76:
+               v = regoff(ctxt, &p.From)
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+               o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+               addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+               o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(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
+}
+
+func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
+       ctxt.Instoffset = 0
+       aclass(ctxt, a)
+       return ctxt.Instoffset
+}
+
+func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
+       return int32(vregoff(ctxt, a))
+}
+
+func oprrr(ctxt *obj.Link, a int) int32 {
+       switch a {
+       case AADD:
+               return int32(OPVCC(31, 266, 0, 0))
+       case AADDCC:
+               return int32(OPVCC(31, 266, 0, 1))
+       case AADDV:
+               return int32(OPVCC(31, 266, 1, 0))
+       case AADDVCC:
+               return int32(OPVCC(31, 266, 1, 1))
+       case AADDC:
+               return int32(OPVCC(31, 10, 0, 0))
+       case AADDCCC:
+               return int32(OPVCC(31, 10, 0, 1))
+       case AADDCV:
+               return int32(OPVCC(31, 10, 1, 0))
+       case AADDCVCC:
+               return int32(OPVCC(31, 10, 1, 1))
+       case AADDE:
+               return int32(OPVCC(31, 138, 0, 0))
+       case AADDECC:
+               return int32(OPVCC(31, 138, 0, 1))
+       case AADDEV:
+               return int32(OPVCC(31, 138, 1, 0))
+       case AADDEVCC:
+               return int32(OPVCC(31, 138, 1, 1))
+       case AADDME:
+               return int32(OPVCC(31, 234, 0, 0))
+       case AADDMECC:
+               return int32(OPVCC(31, 234, 0, 1))
+       case AADDMEV:
+               return int32(OPVCC(31, 234, 1, 0))
+       case AADDMEVCC:
+               return int32(OPVCC(31, 234, 1, 1))
+       case AADDZE:
+               return int32(OPVCC(31, 202, 0, 0))
+       case AADDZECC:
+               return int32(OPVCC(31, 202, 0, 1))
+       case AADDZEV:
+               return int32(OPVCC(31, 202, 1, 0))
+       case AADDZEVCC:
+               return int32(OPVCC(31, 202, 1, 1))
+
+       case AAND:
+               return int32(OPVCC(31, 28, 0, 0))
+       case AANDCC:
+               return int32(OPVCC(31, 28, 0, 1))
+       case AANDN:
+               return int32(OPVCC(31, 60, 0, 0))
+       case AANDNCC:
+               return int32(OPVCC(31, 60, 0, 1))
+
+       case ACMP:
+               return int32(OPVCC(31, 0, 0, 0) | 1<<21) /* L=1 */
+       case ACMPU:
+               return int32(OPVCC(31, 32, 0, 0) | 1<<21)
+       case ACMPW:
+               return int32(OPVCC(31, 0, 0, 0)) /* L=0 */
+       case ACMPWU:
+               return int32(OPVCC(31, 32, 0, 0))
+
+       case ACNTLZW:
+               return int32(OPVCC(31, 26, 0, 0))
+       case ACNTLZWCC:
+               return int32(OPVCC(31, 26, 0, 1))
+       case ACNTLZD:
+               return int32(OPVCC(31, 58, 0, 0))
+       case ACNTLZDCC:
+               return int32(OPVCC(31, 58, 0, 1))
+
+       case ACRAND:
+               return int32(OPVCC(19, 257, 0, 0))
+       case ACRANDN:
+               return int32(OPVCC(19, 129, 0, 0))
+       case ACREQV:
+               return int32(OPVCC(19, 289, 0, 0))
+       case ACRNAND:
+               return int32(OPVCC(19, 225, 0, 0))
+       case ACRNOR:
+               return int32(OPVCC(19, 33, 0, 0))
+       case ACROR:
+               return int32(OPVCC(19, 449, 0, 0))
+       case ACRORN:
+               return int32(OPVCC(19, 417, 0, 0))
+       case ACRXOR:
+               return int32(OPVCC(19, 193, 0, 0))
+
+       case ADCBF:
+               return int32(OPVCC(31, 86, 0, 0))
+       case ADCBI:
+               return int32(OPVCC(31, 470, 0, 0))
+       case ADCBST:
+               return int32(OPVCC(31, 54, 0, 0))
+       case ADCBT:
+               return int32(OPVCC(31, 278, 0, 0))
+       case ADCBTST:
+               return int32(OPVCC(31, 246, 0, 0))
+       case ADCBZ:
+               return int32(OPVCC(31, 1014, 0, 0))
+
+       case AREM,
+               ADIVW:
+               return int32(OPVCC(31, 491, 0, 0))
+
+       case AREMCC,
+               ADIVWCC:
+               return int32(OPVCC(31, 491, 0, 1))
+
+       case AREMV,
+               ADIVWV:
+               return int32(OPVCC(31, 491, 1, 0))
+
+       case AREMVCC,
+               ADIVWVCC:
+               return int32(OPVCC(31, 491, 1, 1))
+
+       case AREMU,
+               ADIVWU:
+               return int32(OPVCC(31, 459, 0, 0))
+
+       case AREMUCC,
+               ADIVWUCC:
+               return int32(OPVCC(31, 459, 0, 1))
+
+       case AREMUV,
+               ADIVWUV:
+               return int32(OPVCC(31, 459, 1, 0))
+
+       case AREMUVCC,
+               ADIVWUVCC:
+               return int32(OPVCC(31, 459, 1, 1))
+
+       case AREMD,
+               ADIVD:
+               return int32(OPVCC(31, 489, 0, 0))
+
+       case AREMDCC,
+               ADIVDCC:
+               return int32(OPVCC(31, 489, 0, 1))
+
+       case AREMDV,
+               ADIVDV:
+               return int32(OPVCC(31, 489, 1, 0))
+
+       case AREMDVCC,
+               ADIVDVCC:
+               return int32(OPVCC(31, 489, 1, 1))
+
+       case AREMDU,
+               ADIVDU:
+               return int32(OPVCC(31, 457, 0, 0))
+
+       case AREMDUCC,
+               ADIVDUCC:
+               return int32(OPVCC(31, 457, 0, 1))
+
+       case AREMDUV,
+               ADIVDUV:
+               return int32(OPVCC(31, 457, 1, 0))
+
+       case AREMDUVCC,
+               ADIVDUVCC:
+               return int32(OPVCC(31, 457, 1, 1))
+
+       case AEIEIO:
+               return int32(OPVCC(31, 854, 0, 0))
+
+       case AEQV:
+               return int32(OPVCC(31, 284, 0, 0))
+       case AEQVCC:
+               return int32(OPVCC(31, 284, 0, 1))
+
+       case AEXTSB:
+               return int32(OPVCC(31, 954, 0, 0))
+       case AEXTSBCC:
+               return int32(OPVCC(31, 954, 0, 1))
+       case AEXTSH:
+               return int32(OPVCC(31, 922, 0, 0))
+       case AEXTSHCC:
+               return int32(OPVCC(31, 922, 0, 1))
+       case AEXTSW:
+               return int32(OPVCC(31, 986, 0, 0))
+       case AEXTSWCC:
+               return int32(OPVCC(31, 986, 0, 1))
+
+       case AFABS:
+               return int32(OPVCC(63, 264, 0, 0))
+       case AFABSCC:
+               return int32(OPVCC(63, 264, 0, 1))
+       case AFADD:
+               return int32(OPVCC(63, 21, 0, 0))
+       case AFADDCC:
+               return int32(OPVCC(63, 21, 0, 1))
+       case AFADDS:
+               return int32(OPVCC(59, 21, 0, 0))
+       case AFADDSCC:
+               return int32(OPVCC(59, 21, 0, 1))
+       case AFCMPO:
+               return int32(OPVCC(63, 32, 0, 0))
+       case AFCMPU:
+               return int32(OPVCC(63, 0, 0, 0))
+       case AFCFID:
+               return int32(OPVCC(63, 846, 0, 0))
+       case AFCFIDCC:
+               return int32(OPVCC(63, 846, 0, 1))
+       case AFCTIW:
+               return int32(OPVCC(63, 14, 0, 0))
+       case AFCTIWCC:
+               return int32(OPVCC(63, 14, 0, 1))
+       case AFCTIWZ:
+               return int32(OPVCC(63, 15, 0, 0))
+       case AFCTIWZCC:
+               return int32(OPVCC(63, 15, 0, 1))
+       case AFCTID:
+               return int32(OPVCC(63, 814, 0, 0))
+       case AFCTIDCC:
+               return int32(OPVCC(63, 814, 0, 1))
+       case AFCTIDZ:
+               return int32(OPVCC(63, 815, 0, 0))
+       case AFCTIDZCC:
+               return int32(OPVCC(63, 815, 0, 1))
+       case AFDIV:
+               return int32(OPVCC(63, 18, 0, 0))
+       case AFDIVCC:
+               return int32(OPVCC(63, 18, 0, 1))
+       case AFDIVS:
+               return int32(OPVCC(59, 18, 0, 0))
+       case AFDIVSCC:
+               return int32(OPVCC(59, 18, 0, 1))
+       case AFMADD:
+               return int32(OPVCC(63, 29, 0, 0))
+       case AFMADDCC:
+               return int32(OPVCC(63, 29, 0, 1))
+       case AFMADDS:
+               return int32(OPVCC(59, 29, 0, 0))
+       case AFMADDSCC:
+               return int32(OPVCC(59, 29, 0, 1))
+
+       case AFMOVS,
+               AFMOVD:
+               return int32(OPVCC(63, 72, 0, 0)) /* load */
+       case AFMOVDCC:
+               return int32(OPVCC(63, 72, 0, 1))
+       case AFMSUB:
+               return int32(OPVCC(63, 28, 0, 0))
+       case AFMSUBCC:
+               return int32(OPVCC(63, 28, 0, 1))
+       case AFMSUBS:
+               return int32(OPVCC(59, 28, 0, 0))
+       case AFMSUBSCC:
+               return int32(OPVCC(59, 28, 0, 1))
+       case AFMUL:
+               return int32(OPVCC(63, 25, 0, 0))
+       case AFMULCC:
+               return int32(OPVCC(63, 25, 0, 1))
+       case AFMULS:
+               return int32(OPVCC(59, 25, 0, 0))
+       case AFMULSCC:
+               return int32(OPVCC(59, 25, 0, 1))
+       case AFNABS:
+               return int32(OPVCC(63, 136, 0, 0))
+       case AFNABSCC:
+               return int32(OPVCC(63, 136, 0, 1))
+       case AFNEG:
+               return int32(OPVCC(63, 40, 0, 0))
+       case AFNEGCC:
+               return int32(OPVCC(63, 40, 0, 1))
+       case AFNMADD:
+               return int32(OPVCC(63, 31, 0, 0))
+       case AFNMADDCC:
+               return int32(OPVCC(63, 31, 0, 1))
+       case AFNMADDS:
+               return int32(OPVCC(59, 31, 0, 0))
+       case AFNMADDSCC:
+               return int32(OPVCC(59, 31, 0, 1))
+       case AFNMSUB:
+               return int32(OPVCC(63, 30, 0, 0))
+       case AFNMSUBCC:
+               return int32(OPVCC(63, 30, 0, 1))
+       case AFNMSUBS:
+               return int32(OPVCC(59, 30, 0, 0))
+       case AFNMSUBSCC:
+               return int32(OPVCC(59, 30, 0, 1))
+       case AFRES:
+               return int32(OPVCC(59, 24, 0, 0))
+       case AFRESCC:
+               return int32(OPVCC(59, 24, 0, 1))
+       case AFRSP:
+               return int32(OPVCC(63, 12, 0, 0))
+       case AFRSPCC:
+               return int32(OPVCC(63, 12, 0, 1))
+       case AFRSQRTE:
+               return int32(OPVCC(63, 26, 0, 0))
+       case AFRSQRTECC:
+               return int32(OPVCC(63, 26, 0, 1))
+       case AFSEL:
+               return int32(OPVCC(63, 23, 0, 0))
+       case AFSELCC:
+               return int32(OPVCC(63, 23, 0, 1))
+       case AFSQRT:
+               return int32(OPVCC(63, 22, 0, 0))
+       case AFSQRTCC:
+               return int32(OPVCC(63, 22, 0, 1))
+       case AFSQRTS:
+               return int32(OPVCC(59, 22, 0, 0))
+       case AFSQRTSCC:
+               return int32(OPVCC(59, 22, 0, 1))
+       case AFSUB:
+               return int32(OPVCC(63, 20, 0, 0))
+       case AFSUBCC:
+               return int32(OPVCC(63, 20, 0, 1))
+       case AFSUBS:
+               return int32(OPVCC(59, 20, 0, 0))
+       case AFSUBSCC:
+               return int32(OPVCC(59, 20, 0, 1))
+
+       case AICBI:
+               return int32(OPVCC(31, 982, 0, 0))
+       case AISYNC:
+               return int32(OPVCC(19, 150, 0, 0))
+
+       case AMTFSB0:
+               return int32(OPVCC(63, 70, 0, 0))
+       case AMTFSB0CC:
+               return int32(OPVCC(63, 70, 0, 1))
+       case AMTFSB1:
+               return int32(OPVCC(63, 38, 0, 0))
+       case AMTFSB1CC:
+               return int32(OPVCC(63, 38, 0, 1))
+
+       case AMULHW:
+               return int32(OPVCC(31, 75, 0, 0))
+       case AMULHWCC:
+               return int32(OPVCC(31, 75, 0, 1))
+       case AMULHWU:
+               return int32(OPVCC(31, 11, 0, 0))
+       case AMULHWUCC:
+               return int32(OPVCC(31, 11, 0, 1))
+       case AMULLW:
+               return int32(OPVCC(31, 235, 0, 0))
+       case AMULLWCC:
+               return int32(OPVCC(31, 235, 0, 1))
+       case AMULLWV:
+               return int32(OPVCC(31, 235, 1, 0))
+       case AMULLWVCC:
+               return int32(OPVCC(31, 235, 1, 1))
+
+       case AMULHD:
+               return int32(OPVCC(31, 73, 0, 0))
+       case AMULHDCC:
+               return int32(OPVCC(31, 73, 0, 1))
+       case AMULHDU:
+               return int32(OPVCC(31, 9, 0, 0))
+       case AMULHDUCC:
+               return int32(OPVCC(31, 9, 0, 1))
+       case AMULLD:
+               return int32(OPVCC(31, 233, 0, 0))
+       case AMULLDCC:
+               return int32(OPVCC(31, 233, 0, 1))
+       case AMULLDV:
+               return int32(OPVCC(31, 233, 1, 0))
+       case AMULLDVCC:
+               return int32(OPVCC(31, 233, 1, 1))
+
+       case ANAND:
+               return int32(OPVCC(31, 476, 0, 0))
+       case ANANDCC:
+               return int32(OPVCC(31, 476, 0, 1))
+       case ANEG:
+               return int32(OPVCC(31, 104, 0, 0))
+       case ANEGCC:
+               return int32(OPVCC(31, 104, 0, 1))
+       case ANEGV:
+               return int32(OPVCC(31, 104, 1, 0))
+       case ANEGVCC:
+               return int32(OPVCC(31, 104, 1, 1))
+       case ANOR:
+               return int32(OPVCC(31, 124, 0, 0))
+       case ANORCC:
+               return int32(OPVCC(31, 124, 0, 1))
+       case AOR:
+               return int32(OPVCC(31, 444, 0, 0))
+       case AORCC:
+               return int32(OPVCC(31, 444, 0, 1))
+       case AORN:
+               return int32(OPVCC(31, 412, 0, 0))
+       case AORNCC:
+               return int32(OPVCC(31, 412, 0, 1))
+
+       case ARFI:
+               return int32(OPVCC(19, 50, 0, 0))
+       case ARFCI:
+               return int32(OPVCC(19, 51, 0, 0))
+       case ARFID:
+               return int32(OPVCC(19, 18, 0, 0))
+       case AHRFID:
+               return int32(OPVCC(19, 274, 0, 0))
+
+       case ARLWMI:
+               return int32(OPVCC(20, 0, 0, 0))
+       case ARLWMICC:
+               return int32(OPVCC(20, 0, 0, 1))
+       case ARLWNM:
+               return int32(OPVCC(23, 0, 0, 0))
+       case ARLWNMCC:
+               return int32(OPVCC(23, 0, 0, 1))
+
+       case ARLDCL:
+               return int32(OPVCC(30, 8, 0, 0))
+       case ARLDCR:
+               return int32(OPVCC(30, 9, 0, 0))
+
+       case ASYSCALL:
+               return int32(OPVCC(17, 1, 0, 0))
+
+       case ASLW:
+               return int32(OPVCC(31, 24, 0, 0))
+       case ASLWCC:
+               return int32(OPVCC(31, 24, 0, 1))
+       case ASLD:
+               return int32(OPVCC(31, 27, 0, 0))
+       case ASLDCC:
+               return int32(OPVCC(31, 27, 0, 1))
+
+       case ASRAW:
+               return int32(OPVCC(31, 792, 0, 0))
+       case ASRAWCC:
+               return int32(OPVCC(31, 792, 0, 1))
+       case ASRAD:
+               return int32(OPVCC(31, 794, 0, 0))
+       case ASRADCC:
+               return int32(OPVCC(31, 794, 0, 1))
+
+       case ASRW:
+               return int32(OPVCC(31, 536, 0, 0))
+       case ASRWCC:
+               return int32(OPVCC(31, 536, 0, 1))
+       case ASRD:
+               return int32(OPVCC(31, 539, 0, 0))
+       case ASRDCC:
+               return int32(OPVCC(31, 539, 0, 1))
+
+       case ASUB:
+               return int32(OPVCC(31, 40, 0, 0))
+       case ASUBCC:
+               return int32(OPVCC(31, 40, 0, 1))
+       case ASUBV:
+               return int32(OPVCC(31, 40, 1, 0))
+       case ASUBVCC:
+               return int32(OPVCC(31, 40, 1, 1))
+       case ASUBC:
+               return int32(OPVCC(31, 8, 0, 0))
+       case ASUBCCC:
+               return int32(OPVCC(31, 8, 0, 1))
+       case ASUBCV:
+               return int32(OPVCC(31, 8, 1, 0))
+       case ASUBCVCC:
+               return int32(OPVCC(31, 8, 1, 1))
+       case ASUBE:
+               return int32(OPVCC(31, 136, 0, 0))
+       case ASUBECC:
+               return int32(OPVCC(31, 136, 0, 1))
+       case ASUBEV:
+               return int32(OPVCC(31, 136, 1, 0))
+       case ASUBEVCC:
+               return int32(OPVCC(31, 136, 1, 1))
+       case ASUBME:
+               return int32(OPVCC(31, 232, 0, 0))
+       case ASUBMECC:
+               return int32(OPVCC(31, 232, 0, 1))
+       case ASUBMEV:
+               return int32(OPVCC(31, 232, 1, 0))
+       case ASUBMEVCC:
+               return int32(OPVCC(31, 232, 1, 1))
+       case ASUBZE:
+               return int32(OPVCC(31, 200, 0, 0))
+       case ASUBZECC:
+               return int32(OPVCC(31, 200, 0, 1))
+       case ASUBZEV:
+               return int32(OPVCC(31, 200, 1, 0))
+       case ASUBZEVCC:
+               return int32(OPVCC(31, 200, 1, 1))
+
+       case ASYNC:
+               return int32(OPVCC(31, 598, 0, 0))
+       case APTESYNC:
+               return int32(OPVCC(31, 598, 0, 0) | 2<<21)
+
+       case ATLBIE:
+               return int32(OPVCC(31, 306, 0, 0))
+       case ATLBIEL:
+               return int32(OPVCC(31, 274, 0, 0))
+       case ATLBSYNC:
+               return int32(OPVCC(31, 566, 0, 0))
+       case ASLBIA:
+               return int32(OPVCC(31, 498, 0, 0))
+       case ASLBIE:
+               return int32(OPVCC(31, 434, 0, 0))
+       case ASLBMFEE:
+               return int32(OPVCC(31, 915, 0, 0))
+       case ASLBMFEV:
+               return int32(OPVCC(31, 851, 0, 0))
+       case ASLBMTE:
+               return int32(OPVCC(31, 402, 0, 0))
+
+       case ATW:
+               return int32(OPVCC(31, 4, 0, 0))
+       case ATD:
+               return int32(OPVCC(31, 68, 0, 0))
+
+       case AXOR:
+               return int32(OPVCC(31, 316, 0, 0))
+       case AXORCC:
+               return int32(OPVCC(31, 316, 0, 1))
+       }
+
+       ctxt.Diag("bad r/r opcode %v", Aconv(a))
+       return 0
+}
+
+func opirr(ctxt *obj.Link, a int) int32 {
+       switch a {
+       case AADD:
+               return int32(OPVCC(14, 0, 0, 0))
+       case AADDC:
+               return int32(OPVCC(12, 0, 0, 0))
+       case AADDCCC:
+               return int32(OPVCC(13, 0, 0, 0))
+       case AADD + AEND:
+               return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */
+
+       case AANDCC:
+               return int32(OPVCC(28, 0, 0, 0))
+       case AANDCC + AEND:
+               return int32(OPVCC(29, 0, 0, 0)) /* ANDIS./ANDIU. */
+
+       case ABR:
+               return int32(OPVCC(18, 0, 0, 0))
+       case ABL:
+               return int32(OPVCC(18, 0, 0, 0) | 1)
+       case ADUFFZERO:
+               return int32(OPVCC(18, 0, 0, 0) | 1)
+       case ADUFFCOPY:
+               return int32(OPVCC(18, 0, 0, 0) | 1)
+       case ABC:
+               return int32(OPVCC(16, 0, 0, 0))
+       case ABCL:
+               return int32(OPVCC(16, 0, 0, 0) | 1)
+
+       case ABEQ:
+               return int32(AOP_RRR(16<<26, 12, 2, 0))
+       case ABGE:
+               return int32(AOP_RRR(16<<26, 4, 0, 0))
+       case ABGT:
+               return int32(AOP_RRR(16<<26, 12, 1, 0))
+       case ABLE:
+               return int32(AOP_RRR(16<<26, 4, 1, 0))
+       case ABLT:
+               return int32(AOP_RRR(16<<26, 12, 0, 0))
+       case ABNE:
+               return int32(AOP_RRR(16<<26, 4, 2, 0))
+       case ABVC:
+               return int32(AOP_RRR(16<<26, 4, 3, 0))
+       case ABVS:
+               return int32(AOP_RRR(16<<26, 12, 3, 0))
+
+       case ACMP:
+               return int32(OPVCC(11, 0, 0, 0) | 1<<21) /* L=1 */
+       case ACMPU:
+               return int32(OPVCC(10, 0, 0, 0) | 1<<21)
+       case ACMPW:
+               return int32(OPVCC(11, 0, 0, 0)) /* L=0 */
+       case ACMPWU:
+               return int32(OPVCC(10, 0, 0, 0))
+       case ALSW:
+               return int32(OPVCC(31, 597, 0, 0))
+
+       case AMULLW:
+               return int32(OPVCC(7, 0, 0, 0))
+
+       case AOR:
+               return int32(OPVCC(24, 0, 0, 0))
+       case AOR + AEND:
+               return int32(OPVCC(25, 0, 0, 0)) /* ORIS/ORIU */
+
+       case ARLWMI:
+               return int32(OPVCC(20, 0, 0, 0)) /* rlwimi */
+       case ARLWMICC:
+               return int32(OPVCC(20, 0, 0, 1))
+       case ARLDMI:
+               return int32(OPVCC(30, 0, 0, 0) | 3<<2) /* rldimi */
+       case ARLDMICC:
+               return int32(OPVCC(30, 0, 0, 1) | 3<<2)
+
+       case ARLWNM:
+               return int32(OPVCC(21, 0, 0, 0)) /* rlwinm */
+       case ARLWNMCC:
+               return int32(OPVCC(21, 0, 0, 1))
+
+       case ARLDCL:
+               return int32(OPVCC(30, 0, 0, 0)) /* rldicl */
+       case ARLDCLCC:
+               return int32(OPVCC(30, 0, 0, 1))
+       case ARLDCR:
+               return int32(OPVCC(30, 1, 0, 0)) /* rldicr */
+       case ARLDCRCC:
+               return int32(OPVCC(30, 1, 0, 1))
+       case ARLDC:
+               return int32(OPVCC(30, 0, 0, 0) | 2<<2)
+       case ARLDCCC:
+               return int32(OPVCC(30, 0, 0, 1) | 2<<2)
+
+       case ASRAW:
+               return int32(OPVCC(31, 824, 0, 0))
+       case ASRAWCC:
+               return int32(OPVCC(31, 824, 0, 1))
+       case ASRAD:
+               return int32(OPVCC(31, (413 << 1), 0, 0))
+       case ASRADCC:
+               return int32(OPVCC(31, (413 << 1), 0, 1))
+
+       case ASTSW:
+               return int32(OPVCC(31, 725, 0, 0))
+
+       case ASUBC:
+               return int32(OPVCC(8, 0, 0, 0))
+
+       case ATW:
+               return int32(OPVCC(3, 0, 0, 0))
+       case ATD:
+               return int32(OPVCC(2, 0, 0, 0))
+
+       case AXOR:
+               return int32(OPVCC(26, 0, 0, 0)) /* XORIL */
+       case AXOR + AEND:
+               return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
+       }
+
+       ctxt.Diag("bad opcode i/r %v", Aconv(a))
+       return 0
+}
+
+/*
+ * load o(a),d
+ */
+func opload(ctxt *obj.Link, a int) int32 {
+
+       switch a {
+       case AMOVD:
+               return int32(OPVCC(58, 0, 0, 0)) /* ld */
+       case AMOVDU:
+               return int32(OPVCC(58, 0, 0, 1)) /* ldu */
+       case AMOVWZ:
+               return int32(OPVCC(32, 0, 0, 0)) /* lwz */
+       case AMOVWZU:
+               return int32(OPVCC(33, 0, 0, 0)) /* lwzu */
+       case AMOVW:
+               return int32(OPVCC(58, 0, 0, 0) | 1<<1) /* lwa */
+
+               /* no AMOVWU */
+       case AMOVB,
+               AMOVBZ:
+               return int32(OPVCC(34, 0, 0, 0))
+               /* load */
+
+       case AMOVBU,
+               AMOVBZU:
+               return int32(OPVCC(35, 0, 0, 0))
+       case AFMOVD:
+               return int32(OPVCC(50, 0, 0, 0))
+       case AFMOVDU:
+               return int32(OPVCC(51, 0, 0, 0))
+       case AFMOVS:
+               return int32(OPVCC(48, 0, 0, 0))
+       case AFMOVSU:
+               return int32(OPVCC(49, 0, 0, 0))
+       case AMOVH:
+               return int32(OPVCC(42, 0, 0, 0))
+       case AMOVHU:
+               return int32(OPVCC(43, 0, 0, 0))
+       case AMOVHZ:
+               return int32(OPVCC(40, 0, 0, 0))
+       case AMOVHZU:
+               return int32(OPVCC(41, 0, 0, 0))
+       case AMOVMW:
+               return int32(OPVCC(46, 0, 0, 0)) /* lmw */
+       }
+
+       ctxt.Diag("bad load opcode %v", Aconv(a))
+       return 0
+}
+
+/*
+ * indexed load a(b),d
+ */
+func oploadx(ctxt *obj.Link, a int) int32 {
+
+       switch a {
+       case AMOVWZ:
+               return int32(OPVCC(31, 23, 0, 0)) /* lwzx */
+       case AMOVWZU:
+               return int32(OPVCC(31, 55, 0, 0)) /* lwzux */
+       case AMOVW:
+               return int32(OPVCC(31, 341, 0, 0)) /* lwax */
+       case AMOVWU:
+               return int32(OPVCC(31, 373, 0, 0)) /* lwaux */
+
+       case AMOVB,
+               AMOVBZ:
+               return int32(OPVCC(31, 87, 0, 0)) /* lbzx */
+
+       case AMOVBU,
+               AMOVBZU:
+               return int32(OPVCC(31, 119, 0, 0)) /* lbzux */
+       case AFMOVD:
+               return int32(OPVCC(31, 599, 0, 0)) /* lfdx */
+       case AFMOVDU:
+               return int32(OPVCC(31, 631, 0, 0)) /*  lfdux */
+       case AFMOVS:
+               return int32(OPVCC(31, 535, 0, 0)) /* lfsx */
+       case AFMOVSU:
+               return int32(OPVCC(31, 567, 0, 0)) /* lfsux */
+       case AMOVH:
+               return int32(OPVCC(31, 343, 0, 0)) /* lhax */
+       case AMOVHU:
+               return int32(OPVCC(31, 375, 0, 0)) /* lhaux */
+       case AMOVHBR:
+               return int32(OPVCC(31, 790, 0, 0)) /* lhbrx */
+       case AMOVWBR:
+               return int32(OPVCC(31, 534, 0, 0)) /* lwbrx */
+       case AMOVHZ:
+               return int32(OPVCC(31, 279, 0, 0)) /* lhzx */
+       case AMOVHZU:
+               return int32(OPVCC(31, 311, 0, 0)) /* lhzux */
+       case AECIWX:
+               return int32(OPVCC(31, 310, 0, 0)) /* eciwx */
+       case ALWAR:
+               return int32(OPVCC(31, 20, 0, 0)) /* lwarx */
+       case ALDAR:
+               return int32(OPVCC(31, 84, 0, 0))
+       case ALSW:
+               return int32(OPVCC(31, 533, 0, 0)) /* lswx */
+       case AMOVD:
+               return int32(OPVCC(31, 21, 0, 0)) /* ldx */
+       case AMOVDU:
+               return int32(OPVCC(31, 53, 0, 0)) /* ldux */
+       }
+
+       ctxt.Diag("bad loadx opcode %v", Aconv(a))
+       return 0
+}
+
+/*
+ * store s,o(d)
+ */
+func opstore(ctxt *obj.Link, a int) int32 {
+
+       switch a {
+       case AMOVB,
+               AMOVBZ:
+               return int32(OPVCC(38, 0, 0, 0)) /* stb */
+
+       case AMOVBU,
+               AMOVBZU:
+               return int32(OPVCC(39, 0, 0, 0)) /* stbu */
+       case AFMOVD:
+               return int32(OPVCC(54, 0, 0, 0)) /* stfd */
+       case AFMOVDU:
+               return int32(OPVCC(55, 0, 0, 0)) /* stfdu */
+       case AFMOVS:
+               return int32(OPVCC(52, 0, 0, 0)) /* stfs */
+       case AFMOVSU:
+               return int32(OPVCC(53, 0, 0, 0)) /* stfsu */
+
+       case AMOVHZ,
+               AMOVH:
+               return int32(OPVCC(44, 0, 0, 0)) /* sth */
+
+       case AMOVHZU,
+               AMOVHU:
+               return int32(OPVCC(45, 0, 0, 0)) /* sthu */
+       case AMOVMW:
+               return int32(OPVCC(47, 0, 0, 0)) /* stmw */
+       case ASTSW:
+               return int32(OPVCC(31, 725, 0, 0)) /* stswi */
+
+       case AMOVWZ,
+               AMOVW:
+               return int32(OPVCC(36, 0, 0, 0)) /* stw */
+
+       case AMOVWZU,
+               AMOVWU:
+               return int32(OPVCC(37, 0, 0, 0)) /* stwu */
+       case AMOVD:
+               return int32(OPVCC(62, 0, 0, 0)) /* std */
+       case AMOVDU:
+               return int32(OPVCC(62, 0, 0, 1)) /* stdu */
+       }
+
+       ctxt.Diag("unknown store opcode %v", Aconv(a))
+       return 0
+}
+
+/*
+ * indexed store s,a(b)
+ */
+func opstorex(ctxt *obj.Link, a int) int32 {
+
+       switch a {
+       case AMOVB,
+               AMOVBZ:
+               return int32(OPVCC(31, 215, 0, 0)) /* stbx */
+
+       case AMOVBU,
+               AMOVBZU:
+               return int32(OPVCC(31, 247, 0, 0)) /* stbux */
+       case AFMOVD:
+               return int32(OPVCC(31, 727, 0, 0)) /* stfdx */
+       case AFMOVDU:
+               return int32(OPVCC(31, 759, 0, 0)) /* stfdux */
+       case AFMOVS:
+               return int32(OPVCC(31, 663, 0, 0)) /* stfsx */
+       case AFMOVSU:
+               return int32(OPVCC(31, 695, 0, 0)) /* stfsux */
+
+       case AMOVHZ,
+               AMOVH:
+               return int32(OPVCC(31, 407, 0, 0)) /* sthx */
+       case AMOVHBR:
+               return int32(OPVCC(31, 918, 0, 0)) /* sthbrx */
+
+       case AMOVHZU,
+               AMOVHU:
+               return int32(OPVCC(31, 439, 0, 0)) /* sthux */
+
+       case AMOVWZ,
+               AMOVW:
+               return int32(OPVCC(31, 151, 0, 0)) /* stwx */
+
+       case AMOVWZU,
+               AMOVWU:
+               return int32(OPVCC(31, 183, 0, 0)) /* stwux */
+       case ASTSW:
+               return int32(OPVCC(31, 661, 0, 0)) /* stswx */
+       case AMOVWBR:
+               return int32(OPVCC(31, 662, 0, 0)) /* stwbrx */
+       case ASTWCCC:
+               return int32(OPVCC(31, 150, 0, 1)) /* stwcx. */
+       case ASTDCCC:
+               return int32(OPVCC(31, 214, 0, 1)) /* stwdx. */
+       case AECOWX:
+               return int32(OPVCC(31, 438, 0, 0)) /* ecowx */
+       case AMOVD:
+               return int32(OPVCC(31, 149, 0, 0)) /* stdx */
+       case AMOVDU:
+               return int32(OPVCC(31, 181, 0, 0)) /* stdux */
+       }
+
+       ctxt.Diag("unknown storex opcode %v", Aconv(a))
+       return 0
+}
diff --git a/src/cmd/internal/obj/ppc64/list9.go b/src/cmd/internal/obj/ppc64/list9.go
new file mode 100644 (file)
index 0000000..1722231
--- /dev/null
@@ -0,0 +1,372 @@
+// cmd/9l/list.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.
+
+package ppc64
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+)
+
+const (
+       STRINGSZ = 1000
+)
+
+//
+// Format conversions
+//     %A int          Opcodes (instruction mnemonics)
+//
+//     %D Addr*        Addresses (instruction operands)
+//             Flags: "%lD": seperate the high and low words of a constant by "-"
+//
+//     %P Prog*        Instructions
+//
+//     %R int          Registers
+//
+//     %$ char*        String constant addresses (for internal use only)
+//     %^ int          C_* classes (for liblink internal use)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+       var str string
+       var fp string
+
+       var a int
+       var ch int
+
+       a = int(p.As)
+
+       if a == ADATA || a == AINIT || a == ADYNT {
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+       } else if a == ATEXT {
+               if p.Reg != 0 {
+                       str = fmt.Sprintf("%.5d (%v)        %v      %v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, fmtLong, &p.To))
+               } else {
+
+                       str = fmt.Sprintf("%.5d (%v)        %v      %v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+               }
+       } else if a == AGLOBL {
+               if p.Reg != 0 {
+                       str = fmt.Sprintf("%.5d (%v)        %v      %v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+               } else {
+
+                       str = fmt.Sprintf("%.5d (%v)        %v      %v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+               }
+       } else {
+
+               if p.Mark&NOSCHED != 0 {
+                       str += fmt.Sprintf("*")
+               }
+               if p.Reg == NREG && p.From3.Type == D_NONE {
+                       str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+               } else if a != ATEXT && p.From.Type == D_OREG {
+                       str += fmt.Sprintf("%.5d (%v)\t%v\t%d(R%d+R%d),%v", p.Pc, p.Line(), Aconv(a), p.From.Offset, p.From.Reg, p.Reg, Dconv(p, 0, &p.To))
+               } else if p.To.Type == D_OREG {
+                       str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%d(R%d+R%d)", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.To.Offset, p.To.Reg, p.Reg)
+               } else {
+
+                       str += fmt.Sprintf("%.5d (%v)\t%v\t%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From))
+                       if p.Reg != NREG {
+                               ch = 'R'
+                               if p.From.Type == D_FREG {
+                                       ch = 'F'
+                               }
+                               str += fmt.Sprintf(",%c%d", ch, p.Reg)
+                       }
+
+                       if p.From3.Type != D_NONE {
+                               str += fmt.Sprintf(",%v", Dconv(p, 0, &p.From3))
+                       }
+                       str += fmt.Sprintf(",%v", Dconv(p, 0, &p.To))
+               }
+
+               if p.Spadj != 0 {
+                       fp += fmt.Sprintf("%s # spadj=%d", str, p.Spadj)
+                       return fp
+               }
+       }
+
+       fp += str
+       return fp
+}
+
+func Aconv(a int) string {
+       var s string
+       var fp string
+
+       s = "???"
+       if a >= AXXX && a < ALAST {
+               s = Anames[a]
+       }
+       fp += s
+       return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+       var str string
+       var fp string
+
+       var v int32
+
+       if flag&fmtLong != 0 /*untyped*/ {
+               if a.Type == D_CONST {
+                       str = fmt.Sprintf("$%d-%d", int32(a.Offset), int32(a.Offset>>32))
+               } else {
+
+                       // ATEXT dst is not constant
+                       str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+               }
+
+               goto ret
+       }
+
+       switch a.Type {
+       default:
+               str = fmt.Sprintf("GOK-type(%d)", a.Type)
+
+       case D_NONE:
+               str = ""
+               if a.Name != D_NONE || a.Reg != NREG || a.Sym != nil {
+                       str = fmt.Sprintf("%v(R%d)(NONE)", Mconv(a), a.Reg)
+               }
+
+       case D_CONST,
+               D_DCONST:
+               if a.Reg != NREG {
+                       str = fmt.Sprintf("$%v(R%d)", Mconv(a), a.Reg)
+               } else {
+
+                       str = fmt.Sprintf("$%v", Mconv(a))
+               }
+
+       case D_OREG:
+               if a.Reg != NREG {
+                       str = fmt.Sprintf("%v(R%d)", Mconv(a), a.Reg)
+               } else {
+
+                       str = fmt.Sprintf("%v", Mconv(a))
+               }
+
+       case D_REG:
+               str = fmt.Sprintf("R%d", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_FREG:
+               str = fmt.Sprintf("F%d", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(F%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_CREG:
+               if a.Reg == NREG {
+                       str = "CR"
+               } else {
+
+                       str = fmt.Sprintf("CR%d", a.Reg)
+               }
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(C%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_SPR:
+               if a.Name == D_NONE && a.Sym == nil {
+                       switch uint32(a.Offset) {
+                       case D_XER:
+                               str = fmt.Sprintf("XER")
+                       case D_LR:
+                               str = fmt.Sprintf("LR")
+                       case D_CTR:
+                               str = fmt.Sprintf("CTR")
+                       default:
+                               str = fmt.Sprintf("SPR(%d)", a.Offset)
+                               break
+                       }
+
+                       break
+               }
+
+               str = fmt.Sprintf("SPR-GOK(%d)", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(SPR-GOK%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_DCR:
+               if a.Name == D_NONE && a.Sym == nil {
+                       str = fmt.Sprintf("DCR(%d)", a.Offset)
+                       break
+               }
+
+               str = fmt.Sprintf("DCR-GOK(%d)", a.Reg)
+               if a.Name != D_NONE || a.Sym != nil {
+                       str = fmt.Sprintf("%v(DCR-GOK%d)(REG)", Mconv(a), a.Reg)
+               }
+
+       case D_OPT:
+               str = fmt.Sprintf("OPT(%d)", a.Reg)
+
+       case D_FPSCR:
+               if a.Reg == NREG {
+                       str = "FPSCR"
+               } else {
+
+                       str = fmt.Sprintf("FPSCR(%d)", a.Reg)
+               }
+
+       case D_MSR:
+               str = fmt.Sprintf("MSR")
+
+       case D_BRANCH:
+               if p.Pcond != nil {
+                       v = int32(p.Pcond.Pc)
+
+                       //if(v >= INITTEXT)
+                       //      v -= INITTEXT-HEADR;
+                       if a.Sym != nil {
+
+                               str = fmt.Sprintf("%s+%.5x(BRANCH)", a.Sym.Name, uint32(v))
+                       } else {
+
+                               str = fmt.Sprintf("%.5x(BRANCH)", uint32(v))
+                       }
+               } else if a.U.Branch != nil {
+                       str = fmt.Sprintf("%d", a.U.Branch.Pc)
+               } else if a.Sym != nil {
+                       str = fmt.Sprintf("%s+%d(APC)", a.Sym.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%d(APC)", a.Offset)
+               }
+
+               //sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
+       case D_FCONST:
+               str = fmt.Sprintf("$%.17g", a.U.Dval)
+
+       case D_SCONST:
+               str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+               break
+       }
+
+ret:
+       fp += str
+       return fp
+}
+
+func Mconv(a *obj.Addr) string {
+       var str string
+       var fp string
+
+       var s *obj.LSym
+       var l int32
+
+       s = a.Sym
+
+       //if(s == nil) {
+       //      l = a->offset;
+       //      if((vlong)l != a->offset)
+       //              sprint(str, "0x%llux", a->offset);
+       //      else
+       //              sprint(str, "%lld", a->offset);
+       //      goto out;
+       //}
+       switch a.Name {
+
+       default:
+               str = fmt.Sprintf("GOK-name(%d)", a.Name)
+
+       case D_NONE:
+               l = int32(a.Offset)
+               if int64(l) != a.Offset {
+                       str = fmt.Sprintf("0x%x", uint64(a.Offset))
+               } else {
+
+                       str = fmt.Sprintf("%d", a.Offset)
+               }
+
+       case D_EXTERN:
+               if a.Offset != 0 {
+                       str = fmt.Sprintf("%s+%d(SB)", s.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%s(SB)", s.Name)
+               }
+
+       case D_STATIC:
+               str = fmt.Sprintf("%s<>+%d(SB)", s.Name, a.Offset)
+
+       case D_AUTO:
+               if s == nil {
+                       str = fmt.Sprintf("%d(SP)", -a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%s-%d(SP)", s.Name, -a.Offset)
+               }
+
+       case D_PARAM:
+               if s == nil {
+                       str = fmt.Sprintf("%d(FP)", a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%s+%d(FP)", s.Name, a.Offset)
+               }
+               break
+       }
+
+       //out:
+       fp += str
+       return fp
+}
+
+func Rconv(r int) string {
+       var str string
+       var fp string
+
+       if r < NREG {
+               str = fmt.Sprintf("r%d", r)
+       } else {
+
+               str = fmt.Sprintf("f%d", r-NREG)
+       }
+       fp += str
+       return fp
+}
+
+func DRconv(a int) string {
+       var s string
+       var fp string
+
+       s = "C_??"
+       if a >= C_NONE && a <= C_NCLASS {
+               s = cnames9[a]
+       }
+       fp += s
+       return fp
+}
diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go
new file mode 100644 (file)
index 0000000..3a25a12
--- /dev/null
@@ -0,0 +1,1148 @@
+// 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.
+
+package ppc64
+
+import (
+       "cmd/internal/obj"
+       "encoding/binary"
+       "fmt"
+       "math"
+)
+
+var zprg = obj.Prog{
+       As:  AGOK,
+       Reg: NREG,
+       From: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+       From3: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+       To: obj.Addr{
+               Name: D_NONE,
+               Type: D_NONE,
+               Reg:  NREG,
+       },
+}
+
+func symtype(a *obj.Addr) int {
+       return int(a.Name)
+}
+
+func isdata(p *obj.Prog) bool {
+       return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+       return p.As == ABL
+}
+
+func datasize(p *obj.Prog) int {
+       return int(p.Reg)
+}
+
+func textflag(p *obj.Prog) int {
+       return int(p.Reg)
+}
+
+func settextflag(p *obj.Prog, f int) {
+       p.Reg = uint8(f)
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+       var literal string
+       var s *obj.LSym
+
+       p.From.Class = 0
+       p.To.Class = 0
+
+       // Rewrite BR/BL to symbol as D_BRANCH.
+       switch p.As {
+
+       case ABR,
+               ABL,
+               ARETURN,
+               ADUFFZERO,
+               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 {
+                       var i32 uint32
+                       var f32 float32
+                       f32 = float32(p.From.U.Dval)
+                       i32 = math.Float32bits(f32)
+                       literal = fmt.Sprintf("$f32.%08x", i32)
+                       s = obj.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
+               }
+
+       case AFMOVD:
+               if p.From.Type == D_FCONST {
+                       var i64 uint64
+                       i64 = math.Float64bits(p.From.U.Dval)
+                       literal = fmt.Sprintf("$f64.%016x", i64)
+                       s = obj.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
+               }
+
+               // Put >32-bit constants in memory and load them
+       case AMOVD:
+               if p.From.Type == D_CONST && p.From.Name == D_NONE && p.From.Reg == NREG && int64(int32(p.From.Offset)) != p.From.Offset {
+
+                       literal = fmt.Sprintf("$i64.%016x", uint64(p.From.Offset))
+                       s = obj.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
+               }
+
+       case ASUBCCC:
+               if p.From.Type == D_CONST {
+                       p.From.Offset = -p.From.Offset
+                       p.As = AADDCCC
+               }
+
+       case ASUB:
+               if p.From.Type == D_CONST {
+                       p.From.Offset = -p.From.Offset
+                       p.As = AADD
+               }
+
+               break
+       }
+}
+
+func parsetextconst(arg int64, textstksiz *int64, textarg *int64) {
+       *textstksiz = arg & 0xffffffff
+       if *textstksiz&0x80000000 != 0 {
+               *textstksiz = -(-*textstksiz & 0xffffffff)
+       }
+
+       *textarg = (arg >> 32) & 0xffffffff
+       if *textarg&0x80000000 != 0 {
+               *textarg = 0
+       }
+       *textarg = (*textarg + 7) &^ 7
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var p1 *obj.Prog
+       var p2 *obj.Prog
+       var q1 *obj.Prog
+       var o int
+       var mov int
+       var aoffset int
+       var textstksiz int64
+       var textarg int64
+       var autosize int32
+
+       if ctxt.Symmorestack[0] == nil {
+               ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+               ctxt.Symmorestack[1] = obj.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)
+
+       cursym.Args = int32(p.To.Offset >> 32)
+       cursym.Locals = int32(textstksiz)
+
+       /*
+        * find leaf subroutines
+        * strip NOPs
+        * expand RET
+        * expand BECOME pseudo
+        */
+       if ctxt.Debugvlog != 0 {
+
+               fmt.Fprintf(ctxt.Bso, "%5.2f noops\n", obj.Cputime())
+       }
+       obj.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 != nil {
+                               p.Link.Mark |= LABEL
+                       }
+
+               case ANOR:
+                       q = p
+                       if p.To.Type == D_REG {
+                               if p.To.Reg == REGZERO {
+                                       p.Mark |= LABEL | SYNC
+                               }
+                       }
+
+               case ALWAR,
+                       ASTWCCC,
+                       AECIWX,
+                       AECOWX,
+                       AEIEIO,
+                       AICBI,
+                       AISYNC,
+                       ATLBIE,
+                       ATLBIEL,
+                       ASLBIA,
+                       ASLBIE,
+                       ASLBMFEE,
+                       ASLBMFEV,
+                       ASLBMTE,
+                       ADCBF,
+                       ADCBI,
+                       ADCBST,
+                       ADCBT,
+                       ADCBTST,
+                       ADCBZ,
+                       ASYNC,
+                       ATLBSYNC,
+                       APTESYNC,
+                       ATW,
+                       AWORD,
+                       ARFI,
+                       ARFCI,
+                       ARFID,
+                       AHRFID:
+                       q = p
+                       p.Mark |= LABEL | SYNC
+                       continue
+
+               case AMOVW,
+                       AMOVWZ,
+                       AMOVD:
+                       q = p
+                       switch p.From.Type {
+                       case D_MSR,
+                               D_SPR,
+                               D_FPSCR,
+                               D_CREG,
+                               D_DCR:
+                               p.Mark |= LABEL | SYNC
+                       }
+
+                       switch p.To.Type {
+                       case D_MSR,
+                               D_SPR,
+                               D_FPSCR,
+                               D_CREG,
+                               D_DCR:
+                               p.Mark |= LABEL | SYNC
+                       }
+
+                       continue
+
+               case AFABS,
+                       AFABSCC,
+                       AFADD,
+                       AFADDCC,
+                       AFCTIW,
+                       AFCTIWCC,
+                       AFCTIWZ,
+                       AFCTIWZCC,
+                       AFDIV,
+                       AFDIVCC,
+                       AFMADD,
+                       AFMADDCC,
+                       AFMOVD,
+                       AFMOVDU,
+                       /* case AFMOVDS: */
+                       AFMOVS,
+                       AFMOVSU,
+
+                       /* case AFMOVSD: */
+                       AFMSUB,
+                       AFMSUBCC,
+                       AFMUL,
+                       AFMULCC,
+                       AFNABS,
+                       AFNABSCC,
+                       AFNEG,
+                       AFNEGCC,
+                       AFNMADD,
+                       AFNMADDCC,
+                       AFNMSUB,
+                       AFNMSUBCC,
+                       AFRSP,
+                       AFRSPCC,
+                       AFSUB,
+                       AFSUBCC:
+                       q = p
+
+                       p.Mark |= FLOAT
+                       continue
+
+               case ABL,
+                       ABCL,
+                       ADUFFZERO,
+                       ADUFFCOPY:
+                       cursym.Text.Mark &^= LEAF
+                       fallthrough
+
+               case ABC,
+                       ABEQ,
+                       ABGE,
+                       ABGT,
+                       ABLE,
+                       ABLT,
+                       ABNE,
+                       ABR,
+                       ABVC,
+                       ABVS:
+                       p.Mark |= BRANCH
+                       q = p
+                       q1 = p.Pcond
+                       if q1 != nil {
+                               for q1.As == ANOP {
+                                       q1 = q1.Link
+                                       p.Pcond = q1
+                               }
+
+                               if !(q1.Mark&LEAF != 0) {
+                                       q1.Mark |= LABEL
+                               }
+                       } else {
+
+                               p.Mark |= LABEL
+                       }
+                       q1 = p.Link
+                       if q1 != nil {
+                               q1.Mark |= LABEL
+                       }
+                       continue
+
+               case AFCMPO,
+                       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 = int(p.As)
+               switch o {
+               case ATEXT:
+                       mov = AMOVD
+                       aoffset = 0
+                       autosize = int32(textstksiz + 8)
+                       if (p.Mark&LEAF != 0) && autosize <= 8 {
+                               autosize = 0
+                       } else if autosize&4 != 0 {
+                               autosize += 4
+                       }
+                       p.To.Offset = int64(uint64(p.To.Offset)&(0xffffffff<<32) | uint64(uint32(autosize-8)))
+
+                       if !(p.Reg&obj.NOSPLIT != 0) {
+                               p = stacksplit(ctxt, p, autosize, bool2int(!(cursym.Text.Reg&obj.NEEDCTXT != 0))) // emit split check
+                       }
+
+                       q = p
+
+                       if autosize != 0 {
+                               /* use MOVDU to adjust R1 when saving R31, if autosize is small */
+                               if !(cursym.Text.Mark&LEAF != 0) && autosize >= -BIG && autosize <= BIG {
+
+                                       mov = AMOVDU
+                                       aoffset = int(-autosize)
+                               } else {
+
+                                       q = obj.Appendp(ctxt, p)
+                                       q.As = AADD
+                                       q.Lineno = p.Lineno
+                                       q.From.Type = D_CONST
+                                       q.From.Offset = int64(-autosize)
+                                       q.To.Type = D_REG
+                                       q.To.Reg = REGSP
+                                       q.Spadj = +autosize
+                               }
+                       } else if !(cursym.Text.Mark&LEAF != 0) {
+                               if ctxt.Debugvlog != 0 {
+                                       fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+                                       obj.Bflush(ctxt.Bso)
+                               }
+
+                               cursym.Text.Mark |= LEAF
+                       }
+
+                       if cursym.Text.Mark&LEAF != 0 {
+                               cursym.Leaf = 1
+                               break
+                       }
+
+                       q = obj.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 = obj.Appendp(ctxt, q)
+                       q.As = int16(mov)
+                       q.Lineno = p.Lineno
+                       q.From.Type = D_REG
+                       q.From.Reg = REGTMP
+                       q.To.Type = D_OREG
+                       q.To.Offset = int64(aoffset)
+                       q.To.Reg = REGSP
+                       if q.As == AMOVDU {
+                               q.Spadj = int32(-aoffset)
+                       }
+
+                       if cursym.Text.Reg&obj.WRAPPER != 0 {
+                               // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+                               //
+                               //      MOVD g_panic(g), R3
+                               //      CMP R0, R3
+                               //      BEQ end
+                               //      MOVD panic_argp(R3), R4
+                               //      ADD $(autosize+8), R1, R5
+                               //      CMP R4, R5
+                               //      BNE end
+                               //      ADD $8, R1, R6
+                               //      MOVD R6, panic_argp(R3)
+                               // end:
+                               //      NOP
+                               //
+                               // The NOP is needed to give the jumps somewhere to land.
+                               // It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes.
+
+                               q = obj.Appendp(ctxt, q)
+
+                               q.As = AMOVD
+                               q.From.Type = D_OREG
+                               q.From.Reg = REGG
+                               q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+                               q.To.Type = D_REG
+                               q.To.Reg = 3
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = ACMP
+                               q.From.Type = D_REG
+                               q.From.Reg = 0
+                               q.To.Type = D_REG
+                               q.To.Reg = 3
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = ABEQ
+                               q.To.Type = D_BRANCH
+                               p1 = q
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = AMOVD
+                               q.From.Type = D_OREG
+                               q.From.Reg = 3
+                               q.From.Offset = 0 // Panic.argp
+                               q.To.Type = D_REG
+                               q.To.Reg = 4
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = AADD
+                               q.From.Type = D_CONST
+                               q.From.Offset = int64(autosize) + 8
+                               q.Reg = REGSP
+                               q.To.Type = D_REG
+                               q.To.Reg = 5
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = ACMP
+                               q.From.Type = D_REG
+                               q.From.Reg = 4
+                               q.To.Type = D_REG
+                               q.To.Reg = 5
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = ABNE
+                               q.To.Type = D_BRANCH
+                               p2 = q
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = AADD
+                               q.From.Type = D_CONST
+                               q.From.Offset = 8
+                               q.Reg = REGSP
+                               q.To.Type = D_REG
+                               q.To.Reg = 6
+
+                               q = obj.Appendp(ctxt, q)
+                               q.As = AMOVD
+                               q.From.Type = D_REG
+                               q.From.Reg = 6
+                               q.To.Type = D_OREG
+                               q.To.Reg = 3
+                               q.To.Offset = 0 // Panic.argp
+
+                               q = obj.Appendp(ctxt, q)
+
+                               q.As = ANOP
+                               p1.Pcond = q
+                               p2.Pcond = q
+                       }
+
+               case ARETURN:
+                       if p.From.Type == D_CONST {
+                               ctxt.Diag("using BECOME (%v) is not supported!", p)
+                               break
+                       }
+
+                       if p.To.Sym != nil { // retjmp
+                               p.As = ABR
+                               p.To.Type = D_BRANCH
+                               break
+                       }
+
+                       if cursym.Text.Mark&LEAF != 0 {
+                               if !(autosize != 0) {
+                                       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 = int64(autosize)
+                               p.To.Type = D_REG
+                               p.To.Reg = REGSP
+                               p.Spadj = -autosize
+
+                               q = ctxt.NewProg()
+                               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.NewProg()
+                       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 false {
+                               // Debug bad returns
+                               q = ctxt.NewProg()
+
+                               q.As = AMOVD
+                               q.Lineno = p.Lineno
+                               q.From.Type = D_OREG
+                               q.From.Offset = 0
+                               q.From.Reg = REGTMP
+                               q.To.Type = D_REG
+                               q.To.Reg = REGTMP
+
+                               q.Link = p.Link
+                               p.Link = q
+                               p = q
+                       }
+
+                       if autosize != 0 {
+                               q = ctxt.NewProg()
+                               q.As = AADD
+                               q.Lineno = p.Lineno
+                               q.From.Type = D_CONST
+                               q.From.Offset = int64(autosize)
+                               q.To.Type = D_REG
+                               q.To.Reg = REGSP
+                               q.Spadj = -autosize
+
+                               q.Link = p.Link
+                               p.Link = q
+                       }
+
+                       q1 = ctxt.NewProg()
+                       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
+
+               case AADD:
+                       if p.To.Type == D_REG && p.To.Reg == REGSP && p.From.Type == D_CONST {
+                               p.Spadj = int32(-p.From.Offset)
+                       }
+                       break
+               }
+       }
+}
+
+/*
+// 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;
+       }
+*/
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int) *obj.Prog {
+
+       var q *obj.Prog
+       var q1 *obj.Prog
+
+       // MOVD g_stackguard(g), R3
+       p = obj.Appendp(ctxt, p)
+
+       p.As = AMOVD
+       p.From.Type = D_OREG
+       p.From.Reg = REGG
+       p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+       if ctxt.Cursym.Cfunc != 0 {
+               p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+       }
+       p.To.Type = D_REG
+       p.To.Reg = 3
+
+       q = nil
+       if framesize <= obj.StackSmall {
+               // small stack: SP < stackguard
+               //      CMP     stackguard, SP
+               p = obj.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 <= obj.StackBig {
+               // large stack: SP-framesize < stackguard-StackSmall
+               //      ADD $-framesize, SP, R4
+               //      CMP stackguard, R4
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AADD
+               p.From.Type = D_CONST
+               p.From.Offset = int64(-framesize)
+               p.Reg = REGSP
+               p.To.Type = D_REG
+               p.To.Reg = 4
+
+               p = obj.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 = obj.Appendp(ctxt, p)
+
+               p.As = ACMP
+               p.From.Type = D_REG
+               p.From.Reg = 3
+               p.To.Type = D_CONST
+               p.To.Offset = obj.StackPreempt
+
+               p = obj.Appendp(ctxt, p)
+               q = p
+               p.As = ABEQ
+               p.To.Type = D_BRANCH
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AADD
+               p.From.Type = D_CONST
+               p.From.Offset = obj.StackGuard
+               p.Reg = REGSP
+               p.To.Type = D_REG
+               p.To.Reg = 4
+
+               p = obj.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 = obj.Appendp(ctxt, p)
+               p.As = AMOVD
+               p.From.Type = D_CONST
+               p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
+               p.To.Type = D_REG
+               p.To.Reg = REGTMP
+
+               p = obj.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
+       p = obj.Appendp(ctxt, p)
+       q1 = p
+
+       p.As = ABLT
+       p.To.Type = D_BRANCH
+
+       // MOVD LR, R5
+       p = obj.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
+       if q != nil {
+               q.Pcond = p
+       }
+
+       // BL   runtime.morestack(SB)
+       p = obj.Appendp(ctxt, p)
+
+       p.As = ABL
+       p.To.Type = D_BRANCH
+       if ctxt.Cursym.Cfunc != 0 {
+               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+       } else {
+
+               p.To.Sym = ctxt.Symmorestack[noctxt]
+       }
+
+       // BR   start
+       p = obj.Appendp(ctxt, p)
+
+       p.As = ABR
+       p.To.Type = D_BRANCH
+       p.Pcond = ctxt.Cursym.Text.Link
+
+       // placeholder for q1's jump target
+       p = obj.Appendp(ctxt, p)
+
+       p.As = ANOP // zero-width place holder
+       q1.Pcond = p
+
+       return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+       var firstp *obj.Prog
+       var lastp *obj.Prog
+
+       ctxt.Cursym = s
+
+       firstp = ctxt.NewProg()
+       lastp = firstp
+       xfol(ctxt, s.Text, &lastp)
+       lastp.Link = nil
+       s.Text = firstp.Link
+}
+
+func relinv(a int) int {
+       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
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+       var q *obj.Prog
+       var r *obj.Prog
+       var a int
+       var b int
+       var i int
+
+loop:
+       if p == nil {
+               return
+       }
+       a = int(p.As)
+       if a == ABR {
+               q = p.Pcond
+               if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
+                       p.Mark |= FOLL
+                       (*last).Link = p
+                       *last = p
+                       p = p.Link
+                       xfol(ctxt, p, last)
+                       p = q
+                       if p != nil && !(p.Mark&FOLL != 0) {
+                               goto loop
+                       }
+                       return
+               }
+
+               if q != nil {
+                       p.Mark |= FOLL
+                       p = q
+                       if !(p.Mark&FOLL != 0) {
+                               goto loop
+                       }
+               }
+       }
+
+       if p.Mark&FOLL != 0 {
+               i = 0
+               q = p
+               for ; i < 4; (func() { i++; q = q.Link })() {
+                       if q == *last || (q.Mark&NOSCHED != 0) {
+                               break
+                       }
+                       b = 0 /* set */
+                       a = int(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 != nil) || (q.Pcond.Mark&FOLL != 0) {
+                               continue
+                       }
+                       b = relinv(a)
+                       if !(b != 0) {
+                               continue
+                       }
+
+               copy:
+                       for {
+                               r = ctxt.NewProg()
+                               *r = *p
+                               if !(r.Mark&FOLL != 0) {
+                                       fmt.Printf("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 = int16(b)
+                               r.Pcond = p.Link
+                               r.Link = p.Pcond
+                               if !(r.Link.Mark&FOLL != 0) {
+                                       xfol(ctxt, r.Link, last)
+                               }
+                               if !(r.Pcond.Mark&FOLL != 0) {
+                                       fmt.Printf("cant happen 2\n")
+                               }
+                               return
+                       }
+               }
+
+               a = ABR
+               q = ctxt.NewProg()
+               q.As = int16(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 != 0 {
+                       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 != 0) {
+                               return
+                       }
+                       goto loop
+               }
+       }
+
+       p = p.Link
+       goto loop
+}
+
+func prg() *obj.Prog {
+       p := zprg
+       return &p
+}
+
+var Linkppc64 = obj.LinkArch{
+       ByteOrder:     binary.BigEndian,
+       Pconv:         Pconv,
+       Name:          "ppc64",
+       Thechar:       '9',
+       Endian:        obj.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,
+       D_OREG:        D_OREG,
+       ACALL:         ABL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          ABR,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARETURN,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
+
+var Linkppc64le = obj.LinkArch{
+       ByteOrder:     binary.LittleEndian,
+       Pconv:         Pconv,
+       Name:          "ppc64le",
+       Thechar:       '9',
+       Endian:        obj.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,
+       D_OREG:        D_OREG,
+       ACALL:         ABL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          ABR,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARETURN,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
diff --git a/src/cmd/internal/obj/ppc64/util.go b/src/cmd/internal/obj/ppc64/util.go
new file mode 100644 (file)
index 0000000..25be412
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ppc64
+
+const (
+       fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+       if b {
+               return 1
+       }
+       return 0
+}
diff --git a/src/cmd/internal/obj/stack.go b/src/cmd/internal/obj/stack.go
new file mode 100644 (file)
index 0000000..4b8c0b4
--- /dev/null
@@ -0,0 +1,52 @@
+// Inferno utils/5l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/span.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.
+
+package obj
+
+// Instruction layout.
+
+// Copyright 2011 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.
+
+// For the linkers. Must match Go definitions.
+// TODO(rsc): Share Go definitions with linkers directly.
+
+const (
+       StackSystem = 0
+       StackBig    = 4096
+       StackGuard  = 640 + StackSystem
+       StackSmall  = 128
+       StackLimit  = StackGuard - StackSystem - StackSmall
+)
+
+const (
+       StackPreempt = -1314 // 0xfff...fade
+)
diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go
new file mode 100644 (file)
index 0000000..855aeea
--- /dev/null
@@ -0,0 +1,286 @@
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.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.
+
+package obj
+
+import (
+       "fmt"
+       "log"
+       "os"
+       "path/filepath"
+)
+
+func yy_isalpha(c int) bool {
+       return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
+}
+
+var headers = []struct {
+       name string
+       val  int
+}{
+       struct {
+               name string
+               val  int
+       }{"android", Hlinux},
+       struct {
+               name string
+               val  int
+       }{"darwin", Hdarwin},
+       struct {
+               name string
+               val  int
+       }{"dragonfly", Hdragonfly},
+       struct {
+               name string
+               val  int
+       }{"elf", Helf},
+       struct {
+               name string
+               val  int
+       }{"freebsd", Hfreebsd},
+       struct {
+               name string
+               val  int
+       }{"linux", Hlinux},
+       struct {
+               name string
+               val  int
+       }{"nacl", Hnacl},
+       struct {
+               name string
+               val  int
+       }{"netbsd", Hnetbsd},
+       struct {
+               name string
+               val  int
+       }{"openbsd", Hopenbsd},
+       struct {
+               name string
+               val  int
+       }{"plan9", Hplan9},
+       struct {
+               name string
+               val  int
+       }{"solaris", Hsolaris},
+       struct {
+               name string
+               val  int
+       }{"windows", Hwindows},
+       struct {
+               name string
+               val  int
+       }{"windowsgui", Hwindows},
+}
+
+func headtype(name string) int {
+       var i int
+
+       for i = 0; i < len(headers); i++ {
+               if name == headers[i].name {
+                       return headers[i].val
+               }
+       }
+       return -1
+}
+
+func Headstr(v int) string {
+       var buf string
+       var i int
+
+       for i = 0; i < len(headers); i++ {
+               if v == headers[i].val {
+                       return headers[i].name
+               }
+       }
+       buf = fmt.Sprintf("%d", v)
+       return buf
+}
+
+func Linknew(arch *LinkArch) *Link {
+       var ctxt *Link
+       var p string
+       var buf string
+
+       ctxt = new(Link)
+       ctxt.Arch = arch
+       ctxt.Version = HistVersion
+       ctxt.Goroot = Getgoroot()
+       ctxt.Goroot_final = os.Getenv("GOROOT_FINAL")
+
+       buf, _ = os.Getwd()
+       if buf == "" {
+               buf = "/???"
+       }
+       buf = filepath.ToSlash(buf)
+
+       ctxt.Pathname = buf
+
+       ctxt.Headtype = headtype(Getgoos())
+       if ctxt.Headtype < 0 {
+               log.Fatalf("unknown goos %s", Getgoos())
+       }
+
+       // Record thread-local storage offset.
+       // TODO(rsc): Move tlsoffset back into the linker.
+       switch ctxt.Headtype {
+
+       default:
+               log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
+
+       case Hplan9,
+               Hwindows:
+               break
+
+               /*
+                * ELF uses TLS offset negative from FS.
+                * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
+                * Known to low-level assembly in package runtime and runtime/cgo.
+                */
+       case Hlinux,
+               Hfreebsd,
+               Hnetbsd,
+               Hopenbsd,
+               Hdragonfly,
+               Hsolaris:
+               ctxt.Tlsoffset = -2 * ctxt.Arch.Ptrsize
+
+       case Hnacl:
+               switch ctxt.Arch.Thechar {
+               default:
+                       log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
+
+               case '6':
+                       ctxt.Tlsoffset = 0
+
+               case '8':
+                       ctxt.Tlsoffset = -8
+
+               case '5':
+                       ctxt.Tlsoffset = 0
+                       break
+               }
+
+               /*
+                * OS X system constants - offset from 0(GS) to our TLS.
+                * Explained in ../../runtime/cgo/gcc_darwin_*.c.
+                */
+       case Hdarwin:
+               switch ctxt.Arch.Thechar {
+
+               default:
+                       log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
+
+               case '6':
+                       ctxt.Tlsoffset = 0x8a0
+
+               case '8':
+                       ctxt.Tlsoffset = 0x468
+                       break
+               }
+
+               break
+       }
+
+       // On arm, record goarm.
+       if ctxt.Arch.Thechar == '5' {
+
+               p = Getgoarm()
+               if p != "" {
+                       ctxt.Goarm = int32(Atoi(p))
+               } else {
+
+                       ctxt.Goarm = 6
+               }
+       }
+
+       return ctxt
+}
+
+func linknewsym(ctxt *Link, symb string, v int) *LSym {
+       var s *LSym
+
+       s = new(LSym)
+       *s = LSym{}
+
+       s.Dynid = -1
+       s.Plt = -1
+       s.Got = -1
+       s.Name = symb
+       s.Type = 0
+       s.Version = int16(v)
+       s.Value = 0
+       s.Sig = 0
+       s.Size = 0
+       ctxt.Nsymbol++
+
+       s.Allsym = ctxt.Allsym
+       ctxt.Allsym = s
+
+       return s
+}
+
+func _lookup(ctxt *Link, symb string, v int, creat int) *LSym {
+       var s *LSym
+       var h uint32
+
+       h = uint32(v)
+       for i := 0; i < len(symb); i++ {
+               c := int(symb[i])
+               h = h + h + h + uint32(c)
+       }
+       h &= 0xffffff
+       h %= LINKHASH
+       for s = ctxt.Hash[h]; s != nil; s = s.Hash {
+               if int(s.Version) == v && s.Name == symb {
+                       return s
+               }
+       }
+       if !(creat != 0) {
+               return nil
+       }
+
+       s = linknewsym(ctxt, symb, v)
+       s.Extname = s.Name
+       s.Hash = ctxt.Hash[h]
+       ctxt.Hash[h] = s
+
+       return s
+}
+
+func Linklookup(ctxt *Link, name string, v int) *LSym {
+       return _lookup(ctxt, name, v, 1)
+}
+
+// read-only lookup
+func linkrlookup(ctxt *Link, name string, v int) *LSym {
+
+       return _lookup(ctxt, name, v, 0)
+}
diff --git a/src/cmd/internal/obj/textflag.go b/src/cmd/internal/obj/textflag.go
new file mode 100644 (file)
index 0000000..e0e641d
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2013 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.
+
+// This file defines flags attached to various functions
+// and data objects.  The compilers, assemblers, and linker must
+// all agree on these values.
+
+package obj
+
+const (
+       // Don't profile the marked routine.  This flag is deprecated.
+       NOPROF = 1
+
+       // It is ok for the linker to get multiple of these symbols.  It will
+       // pick one of the duplicates to use.
+       DUPOK = 2
+
+       // Don't insert stack check preamble.
+       NOSPLIT = 4
+
+       // Put this data in a read-only section.
+       RODATA = 8
+
+       // This data contains no pointers.
+       NOPTR = 16
+
+       // This is a wrapper function and should not count as disabling 'recover'.
+       WRAPPER = 32
+
+       // This function uses its incoming context register.
+       NEEDCTXT = 64
+)
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
new file mode 100644 (file)
index 0000000..14f2271
--- /dev/null
@@ -0,0 +1,125 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package obj
+
+import (
+       "bufio"
+       "fmt"
+       "io"
+       "os"
+       "strconv"
+       "time"
+)
+
+var start time.Time
+
+func Cputime() float64 {
+       if start.IsZero() {
+               start = time.Now()
+       }
+       return time.Since(start).Seconds()
+}
+
+type Biobuf struct {
+       unget     int
+       haveUnget bool
+       r         *bufio.Reader
+       w         *bufio.Writer
+}
+
+func Binitw(w io.Writer) *Biobuf {
+       return &Biobuf{w: bufio.NewWriter(w)}
+}
+
+func (b *Biobuf) Write(p []byte) (int, error) {
+       return b.w.Write(p)
+}
+
+func (b *Biobuf) Flush() error {
+       return b.w.Flush()
+}
+
+func Bwrite(b *Biobuf, p []byte) (int, error) {
+       return b.w.Write(p)
+}
+
+func Bputc(b *Biobuf, c byte) {
+       b.w.WriteByte(c)
+}
+
+func Bgetc(b *Biobuf) int {
+       if b.haveUnget {
+               b.haveUnget = false
+               return int(b.unget)
+       }
+       c, err := b.r.ReadByte()
+       if err != nil {
+               b.unget = -1
+               return -1
+       }
+       b.unget = int(c)
+       return int(c)
+}
+
+func Bungetc(b *Biobuf) {
+       b.haveUnget = true
+}
+
+func Boffset(b *Biobuf) int64 {
+       panic("Boffset")
+}
+
+func Bflush(b *Biobuf) error {
+       return b.w.Flush()
+}
+
+func envOr(key, value string) string {
+       if x := os.Getenv(key); x != "" {
+               return x
+       }
+       return value
+}
+
+func Getgoroot() string {
+       return envOr("GOROOT", defaultGOROOT)
+}
+
+func Getgoarch() string {
+       return envOr("GOARCH", defaultGOARCH)
+}
+
+func Getgoos() string {
+       return envOr("GOOS", defaultGOOS)
+}
+
+func Getgoarm() string {
+       return envOr("GOARM", defaultGOARM)
+}
+
+func Getgoversion() string {
+       return version
+}
+
+func Atoi(s string) int {
+       i, _ := strconv.Atoi(s)
+       return i
+}
+
+func (p *Prog) Line() string {
+       return linklinefmt(p.Ctxt, int(p.Lineno), false, false)
+}
+
+func (p *Prog) String() string {
+       if p.Ctxt == nil {
+               return fmt.Sprintf("<Prog without ctxt>")
+       }
+       return p.Ctxt.Arch.Pconv(p)
+}
+
+func (ctxt *Link) NewProg() *Prog {
+       p := ctxt.Arch.Prg() // should be the only call to this; all others should use ctxt.NewProg
+       p.Ctxt = ctxt
+       return p
+}
diff --git a/src/cmd/internal/obj/x86/6.out.go b/src/cmd/internal/obj/x86/6.out.go
new file mode 100644 (file)
index 0000000..f19c0cd
--- /dev/null
@@ -0,0 +1,836 @@
+// Inferno utils/6c/6.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/6.out.h
+//
+//     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.
+
+package x86
+
+/*
+ *     amd64
+ */
+const (
+       AXXX = iota
+       AAAA
+       AAAD
+       AAAM
+       AAAS
+       AADCB
+       AADCL
+       AADCW
+       AADDB
+       AADDL
+       AADDW
+       AADJSP
+       AANDB
+       AANDL
+       AANDW
+       AARPL
+       ABOUNDL
+       ABOUNDW
+       ABSFL
+       ABSFW
+       ABSRL
+       ABSRW
+       ABTL
+       ABTW
+       ABTCL
+       ABTCW
+       ABTRL
+       ABTRW
+       ABTSL
+       ABTSW
+       ABYTE
+       ACALL
+       ACLC
+       ACLD
+       ACLI
+       ACLTS
+       ACMC
+       ACMPB
+       ACMPL
+       ACMPW
+       ACMPSB
+       ACMPSL
+       ACMPSW
+       ADAA
+       ADAS
+       ADATA
+       ADECB
+       ADECL
+       ADECQ
+       ADECW
+       ADIVB
+       ADIVL
+       ADIVW
+       AENTER
+       AGLOBL
+       AGOK
+       AHISTORY
+       AHLT
+       AIDIVB
+       AIDIVL
+       AIDIVW
+       AIMULB
+       AIMULL
+       AIMULW
+       AINB
+       AINL
+       AINW
+       AINCB
+       AINCL
+       AINCQ
+       AINCW
+       AINSB
+       AINSL
+       AINSW
+       AINT
+       AINTO
+       AIRETL
+       AIRETW
+       AJCC
+       AJCS
+       AJCXZL
+       AJEQ
+       AJGE
+       AJGT
+       AJHI
+       AJLE
+       AJLS
+       AJLT
+       AJMI
+       AJMP
+       AJNE
+       AJOC
+       AJOS
+       AJPC
+       AJPL
+       AJPS
+       ALAHF
+       ALARL
+       ALARW
+       ALEAL
+       ALEAW
+       ALEAVEL
+       ALEAVEW
+       ALOCK
+       ALODSB
+       ALODSL
+       ALODSW
+       ALONG
+       ALOOP
+       ALOOPEQ
+       ALOOPNE
+       ALSLL
+       ALSLW
+       AMOVB
+       AMOVL
+       AMOVW
+       AMOVBLSX
+       AMOVBLZX
+       AMOVBQSX
+       AMOVBQZX
+       AMOVBWSX
+       AMOVBWZX
+       AMOVWLSX
+       AMOVWLZX
+       AMOVWQSX
+       AMOVWQZX
+       AMOVSB
+       AMOVSL
+       AMOVSW
+       AMULB
+       AMULL
+       AMULW
+       ANAME
+       ANEGB
+       ANEGL
+       ANEGW
+       ANOP
+       ANOTB
+       ANOTL
+       ANOTW
+       AORB
+       AORL
+       AORW
+       AOUTB
+       AOUTL
+       AOUTW
+       AOUTSB
+       AOUTSL
+       AOUTSW
+       APAUSE
+       APOPAL
+       APOPAW
+       APOPFL
+       APOPFW
+       APOPL
+       APOPW
+       APUSHAL
+       APUSHAW
+       APUSHFL
+       APUSHFW
+       APUSHL
+       APUSHW
+       ARCLB
+       ARCLL
+       ARCLW
+       ARCRB
+       ARCRL
+       ARCRW
+       AREP
+       AREPN
+       ARET
+       AROLB
+       AROLL
+       AROLW
+       ARORB
+       ARORL
+       ARORW
+       ASAHF
+       ASALB
+       ASALL
+       ASALW
+       ASARB
+       ASARL
+       ASARW
+       ASBBB
+       ASBBL
+       ASBBW
+       ASCASB
+       ASCASL
+       ASCASW
+       ASETCC
+       ASETCS
+       ASETEQ
+       ASETGE
+       ASETGT
+       ASETHI
+       ASETLE
+       ASETLS
+       ASETLT
+       ASETMI
+       ASETNE
+       ASETOC
+       ASETOS
+       ASETPC
+       ASETPL
+       ASETPS
+       ACDQ
+       ACWD
+       ASHLB
+       ASHLL
+       ASHLW
+       ASHRB
+       ASHRL
+       ASHRW
+       ASTC
+       ASTD
+       ASTI
+       ASTOSB
+       ASTOSL
+       ASTOSW
+       ASUBB
+       ASUBL
+       ASUBW
+       ASYSCALL
+       ATESTB
+       ATESTL
+       ATESTW
+       ATEXT
+       AVERR
+       AVERW
+       AWAIT
+       AWORD
+       AXCHGB
+       AXCHGL
+       AXCHGW
+       AXLAT
+       AXORB
+       AXORL
+       AXORW
+       AFMOVB
+       AFMOVBP
+       AFMOVD
+       AFMOVDP
+       AFMOVF
+       AFMOVFP
+       AFMOVL
+       AFMOVLP
+       AFMOVV
+       AFMOVVP
+       AFMOVW
+       AFMOVWP
+       AFMOVX
+       AFMOVXP
+       AFCOMB
+       AFCOMBP
+       AFCOMD
+       AFCOMDP
+       AFCOMDPP
+       AFCOMF
+       AFCOMFP
+       AFCOML
+       AFCOMLP
+       AFCOMW
+       AFCOMWP
+       AFUCOM
+       AFUCOMP
+       AFUCOMPP
+       AFADDDP
+       AFADDW
+       AFADDL
+       AFADDF
+       AFADDD
+       AFMULDP
+       AFMULW
+       AFMULL
+       AFMULF
+       AFMULD
+       AFSUBDP
+       AFSUBW
+       AFSUBL
+       AFSUBF
+       AFSUBD
+       AFSUBRDP
+       AFSUBRW
+       AFSUBRL
+       AFSUBRF
+       AFSUBRD
+       AFDIVDP
+       AFDIVW
+       AFDIVL
+       AFDIVF
+       AFDIVD
+       AFDIVRDP
+       AFDIVRW
+       AFDIVRL
+       AFDIVRF
+       AFDIVRD
+       AFXCHD
+       AFFREE
+       AFLDCW
+       AFLDENV
+       AFRSTOR
+       AFSAVE
+       AFSTCW
+       AFSTENV
+       AFSTSW
+       AF2XM1
+       AFABS
+       AFCHS
+       AFCLEX
+       AFCOS
+       AFDECSTP
+       AFINCSTP
+       AFINIT
+       AFLD1
+       AFLDL2E
+       AFLDL2T
+       AFLDLG2
+       AFLDLN2
+       AFLDPI
+       AFLDZ
+       AFNOP
+       AFPATAN
+       AFPREM
+       AFPREM1
+       AFPTAN
+       AFRNDINT
+       AFSCALE
+       AFSIN
+       AFSINCOS
+       AFSQRT
+       AFTST
+       AFXAM
+       AFXTRACT
+       AFYL2X
+       AFYL2XP1
+       AEND
+       ADYNT_
+       AINIT_
+       ASIGNAME
+       ACMPXCHGB
+       ACMPXCHGL
+       ACMPXCHGW
+       ACMPXCHG8B
+       ACPUID
+       AINVD
+       AINVLPG
+       ALFENCE
+       AMFENCE
+       AMOVNTIL
+       ARDMSR
+       ARDPMC
+       ARDTSC
+       ARSM
+       ASFENCE
+       ASYSRET
+       AWBINVD
+       AWRMSR
+       AXADDB
+       AXADDL
+       AXADDW
+       ACMOVLCC
+       ACMOVLCS
+       ACMOVLEQ
+       ACMOVLGE
+       ACMOVLGT
+       ACMOVLHI
+       ACMOVLLE
+       ACMOVLLS
+       ACMOVLLT
+       ACMOVLMI
+       ACMOVLNE
+       ACMOVLOC
+       ACMOVLOS
+       ACMOVLPC
+       ACMOVLPL
+       ACMOVLPS
+       ACMOVQCC
+       ACMOVQCS
+       ACMOVQEQ
+       ACMOVQGE
+       ACMOVQGT
+       ACMOVQHI
+       ACMOVQLE
+       ACMOVQLS
+       ACMOVQLT
+       ACMOVQMI
+       ACMOVQNE
+       ACMOVQOC
+       ACMOVQOS
+       ACMOVQPC
+       ACMOVQPL
+       ACMOVQPS
+       ACMOVWCC
+       ACMOVWCS
+       ACMOVWEQ
+       ACMOVWGE
+       ACMOVWGT
+       ACMOVWHI
+       ACMOVWLE
+       ACMOVWLS
+       ACMOVWLT
+       ACMOVWMI
+       ACMOVWNE
+       ACMOVWOC
+       ACMOVWOS
+       ACMOVWPC
+       ACMOVWPL
+       ACMOVWPS
+       AADCQ
+       AADDQ
+       AANDQ
+       ABSFQ
+       ABSRQ
+       ABTCQ
+       ABTQ
+       ABTRQ
+       ABTSQ
+       ACMPQ
+       ACMPSQ
+       ACMPXCHGQ
+       ACQO
+       ADIVQ
+       AIDIVQ
+       AIMULQ
+       AIRETQ
+       AJCXZQ
+       ALEAQ
+       ALEAVEQ
+       ALODSQ
+       AMOVQ
+       AMOVLQSX
+       AMOVLQZX
+       AMOVNTIQ
+       AMOVSQ
+       AMULQ
+       ANEGQ
+       ANOTQ
+       AORQ
+       APOPFQ
+       APOPQ
+       APUSHFQ
+       APUSHQ
+       ARCLQ
+       ARCRQ
+       AROLQ
+       ARORQ
+       AQUAD
+       ASALQ
+       ASARQ
+       ASBBQ
+       ASCASQ
+       ASHLQ
+       ASHRQ
+       ASTOSQ
+       ASUBQ
+       ATESTQ
+       AXADDQ
+       AXCHGQ
+       AXORQ
+       AADDPD
+       AADDPS
+       AADDSD
+       AADDSS
+       AANDNPD
+       AANDNPS
+       AANDPD
+       AANDPS
+       ACMPPD
+       ACMPPS
+       ACMPSD
+       ACMPSS
+       ACOMISD
+       ACOMISS
+       ACVTPD2PL
+       ACVTPD2PS
+       ACVTPL2PD
+       ACVTPL2PS
+       ACVTPS2PD
+       ACVTPS2PL
+       ACVTSD2SL
+       ACVTSD2SQ
+       ACVTSD2SS
+       ACVTSL2SD
+       ACVTSL2SS
+       ACVTSQ2SD
+       ACVTSQ2SS
+       ACVTSS2SD
+       ACVTSS2SL
+       ACVTSS2SQ
+       ACVTTPD2PL
+       ACVTTPS2PL
+       ACVTTSD2SL
+       ACVTTSD2SQ
+       ACVTTSS2SL
+       ACVTTSS2SQ
+       ADIVPD
+       ADIVPS
+       ADIVSD
+       ADIVSS
+       AEMMS
+       AFXRSTOR
+       AFXRSTOR64
+       AFXSAVE
+       AFXSAVE64
+       ALDMXCSR
+       AMASKMOVOU
+       AMASKMOVQ
+       AMAXPD
+       AMAXPS
+       AMAXSD
+       AMAXSS
+       AMINPD
+       AMINPS
+       AMINSD
+       AMINSS
+       AMOVAPD
+       AMOVAPS
+       AMOVOU
+       AMOVHLPS
+       AMOVHPD
+       AMOVHPS
+       AMOVLHPS
+       AMOVLPD
+       AMOVLPS
+       AMOVMSKPD
+       AMOVMSKPS
+       AMOVNTO
+       AMOVNTPD
+       AMOVNTPS
+       AMOVNTQ
+       AMOVO
+       AMOVQOZX
+       AMOVSD
+       AMOVSS
+       AMOVUPD
+       AMOVUPS
+       AMULPD
+       AMULPS
+       AMULSD
+       AMULSS
+       AORPD
+       AORPS
+       APACKSSLW
+       APACKSSWB
+       APACKUSWB
+       APADDB
+       APADDL
+       APADDQ
+       APADDSB
+       APADDSW
+       APADDUSB
+       APADDUSW
+       APADDW
+       APANDB
+       APANDL
+       APANDSB
+       APANDSW
+       APANDUSB
+       APANDUSW
+       APANDW
+       APAND
+       APANDN
+       APAVGB
+       APAVGW
+       APCMPEQB
+       APCMPEQL
+       APCMPEQW
+       APCMPGTB
+       APCMPGTL
+       APCMPGTW
+       APEXTRW
+       APFACC
+       APFADD
+       APFCMPEQ
+       APFCMPGE
+       APFCMPGT
+       APFMAX
+       APFMIN
+       APFMUL
+       APFNACC
+       APFPNACC
+       APFRCP
+       APFRCPIT1
+       APFRCPI2T
+       APFRSQIT1
+       APFRSQRT
+       APFSUB
+       APFSUBR
+       APINSRW
+       APINSRD
+       APINSRQ
+       APMADDWL
+       APMAXSW
+       APMAXUB
+       APMINSW
+       APMINUB
+       APMOVMSKB
+       APMULHRW
+       APMULHUW
+       APMULHW
+       APMULLW
+       APMULULQ
+       APOR
+       APSADBW
+       APSHUFHW
+       APSHUFL
+       APSHUFLW
+       APSHUFW
+       APSHUFB
+       APSLLO
+       APSLLL
+       APSLLQ
+       APSLLW
+       APSRAL
+       APSRAW
+       APSRLO
+       APSRLL
+       APSRLQ
+       APSRLW
+       APSUBB
+       APSUBL
+       APSUBQ
+       APSUBSB
+       APSUBSW
+       APSUBUSB
+       APSUBUSW
+       APSUBW
+       APSWAPL
+       APUNPCKHBW
+       APUNPCKHLQ
+       APUNPCKHQDQ
+       APUNPCKHWL
+       APUNPCKLBW
+       APUNPCKLLQ
+       APUNPCKLQDQ
+       APUNPCKLWL
+       APXOR
+       ARCPPS
+       ARCPSS
+       ARSQRTPS
+       ARSQRTSS
+       ASHUFPD
+       ASHUFPS
+       ASQRTPD
+       ASQRTPS
+       ASQRTSD
+       ASQRTSS
+       ASTMXCSR
+       ASUBPD
+       ASUBPS
+       ASUBSD
+       ASUBSS
+       AUCOMISD
+       AUCOMISS
+       AUNPCKHPD
+       AUNPCKHPS
+       AUNPCKLPD
+       AUNPCKLPS
+       AXORPD
+       AXORPS
+       APF2IW
+       APF2IL
+       API2FW
+       API2FL
+       ARETFW
+       ARETFL
+       ARETFQ
+       ASWAPGS
+       AMODE
+       ACRC32B
+       ACRC32Q
+       AIMUL3Q
+       APREFETCHT0
+       APREFETCHT1
+       APREFETCHT2
+       APREFETCHNTA
+       AMOVQL
+       ABSWAPL
+       ABSWAPQ
+       AUNDEF
+       AAESENC
+       AAESENCLAST
+       AAESDEC
+       AAESDECLAST
+       AAESIMC
+       AAESKEYGENASSIST
+       APSHUFD
+       APCLMULQDQ
+       AUSEFIELD
+       ATYPE
+       AFUNCDATA
+       APCDATA
+       ACHECKNIL
+       AVARDEF
+       AVARKILL
+       ADUFFCOPY
+       ADUFFZERO
+       ALAST
+)
+
+const (
+       D_AL = 0 + iota
+       D_CL
+       D_DL
+       D_BL
+       D_SPB
+       D_BPB
+       D_SIB
+       D_DIB
+       D_R8B
+       D_R9B
+       D_R10B
+       D_R11B
+       D_R12B
+       D_R13B
+       D_R14B
+       D_R15B
+       D_AX = 16 + iota - 16
+       D_CX
+       D_DX
+       D_BX
+       D_SP
+       D_BP
+       D_SI
+       D_DI
+       D_R8
+       D_R9
+       D_R10
+       D_R11
+       D_R12
+       D_R13
+       D_R14
+       D_R15
+       D_AH = 32 + iota - 32
+       D_CH
+       D_DH
+       D_BH
+       D_F0 = 36
+       D_M0 = 44
+       D_X0 = 52 + iota - 38
+       D_X1
+       D_X2
+       D_X3
+       D_X4
+       D_X5
+       D_X6
+       D_X7
+       D_X8
+       D_X9
+       D_X10
+       D_X11
+       D_X12
+       D_X13
+       D_X14
+       D_X15
+       D_CS = 68 + iota - 54
+       D_SS
+       D_DS
+       D_ES
+       D_FS
+       D_GS
+       D_GDTR
+       D_IDTR
+       D_LDTR
+       D_MSW
+       D_TASK
+       D_CR     = 79
+       D_DR     = 95
+       D_TR     = 103
+       D_TLS    = 111
+       D_NONE   = 112
+       D_BRANCH = 113
+       D_EXTERN = 114
+       D_STATIC = 115
+       D_AUTO   = 116
+       D_PARAM  = 117
+       D_CONST  = 118
+       D_FCONST = 119
+       D_SCONST = 120
+       D_ADDR   = 121 + iota - 78
+       D_INDIR
+       D_LAST
+       T_TYPE   = 1 << 0
+       T_INDEX  = 1 << 1
+       T_OFFSET = 1 << 2
+       T_FCONST = 1 << 3
+       T_SYM    = 1 << 4
+       T_SCONST = 1 << 5
+       T_64     = 1 << 6
+       T_GOTYPE = 1 << 7
+       REGARG   = -1
+       REGRET   = D_AX
+       FREGRET  = D_X0
+       REGSP    = D_SP
+       REGTMP   = D_DI
+       REGEXT   = D_R15
+       FREGMIN  = D_X0 + 5
+       FREGEXT  = D_X0 + 15
+)
diff --git a/src/cmd/internal/obj/x86/anames6.go b/src/cmd/internal/obj/x86/anames6.go
new file mode 100644 (file)
index 0000000..4d8a0b0
--- /dev/null
@@ -0,0 +1,789 @@
+package x86
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+       "XXX",
+       "AAA",
+       "AAD",
+       "AAM",
+       "AAS",
+       "ADCB",
+       "ADCL",
+       "ADCW",
+       "ADDB",
+       "ADDL",
+       "ADDW",
+       "ADJSP",
+       "ANDB",
+       "ANDL",
+       "ANDW",
+       "ARPL",
+       "BOUNDL",
+       "BOUNDW",
+       "BSFL",
+       "BSFW",
+       "BSRL",
+       "BSRW",
+       "BTL",
+       "BTW",
+       "BTCL",
+       "BTCW",
+       "BTRL",
+       "BTRW",
+       "BTSL",
+       "BTSW",
+       "BYTE",
+       "CALL",
+       "CLC",
+       "CLD",
+       "CLI",
+       "CLTS",
+       "CMC",
+       "CMPB",
+       "CMPL",
+       "CMPW",
+       "CMPSB",
+       "CMPSL",
+       "CMPSW",
+       "DAA",
+       "DAS",
+       "DATA",
+       "DECB",
+       "DECL",
+       "DECQ",
+       "DECW",
+       "DIVB",
+       "DIVL",
+       "DIVW",
+       "ENTER",
+       "GLOBL",
+       "GOK",
+       "HISTORY",
+       "HLT",
+       "IDIVB",
+       "IDIVL",
+       "IDIVW",
+       "IMULB",
+       "IMULL",
+       "IMULW",
+       "INB",
+       "INL",
+       "INW",
+       "INCB",
+       "INCL",
+       "INCQ",
+       "INCW",
+       "INSB",
+       "INSL",
+       "INSW",
+       "INT",
+       "INTO",
+       "IRETL",
+       "IRETW",
+       "JCC",
+       "JCS",
+       "JCXZL",
+       "JEQ",
+       "JGE",
+       "JGT",
+       "JHI",
+       "JLE",
+       "JLS",
+       "JLT",
+       "JMI",
+       "JMP",
+       "JNE",
+       "JOC",
+       "JOS",
+       "JPC",
+       "JPL",
+       "JPS",
+       "LAHF",
+       "LARL",
+       "LARW",
+       "LEAL",
+       "LEAW",
+       "LEAVEL",
+       "LEAVEW",
+       "LOCK",
+       "LODSB",
+       "LODSL",
+       "LODSW",
+       "LONG",
+       "LOOP",
+       "LOOPEQ",
+       "LOOPNE",
+       "LSLL",
+       "LSLW",
+       "MOVB",
+       "MOVL",
+       "MOVW",
+       "MOVBLSX",
+       "MOVBLZX",
+       "MOVBQSX",
+       "MOVBQZX",
+       "MOVBWSX",
+       "MOVBWZX",
+       "MOVWLSX",
+       "MOVWLZX",
+       "MOVWQSX",
+       "MOVWQZX",
+       "MOVSB",
+       "MOVSL",
+       "MOVSW",
+       "MULB",
+       "MULL",
+       "MULW",
+       "NAME",
+       "NEGB",
+       "NEGL",
+       "NEGW",
+       "NOP",
+       "NOTB",
+       "NOTL",
+       "NOTW",
+       "ORB",
+       "ORL",
+       "ORW",
+       "OUTB",
+       "OUTL",
+       "OUTW",
+       "OUTSB",
+       "OUTSL",
+       "OUTSW",
+       "PAUSE",
+       "POPAL",
+       "POPAW",
+       "POPFL",
+       "POPFW",
+       "POPL",
+       "POPW",
+       "PUSHAL",
+       "PUSHAW",
+       "PUSHFL",
+       "PUSHFW",
+       "PUSHL",
+       "PUSHW",
+       "RCLB",
+       "RCLL",
+       "RCLW",
+       "RCRB",
+       "RCRL",
+       "RCRW",
+       "REP",
+       "REPN",
+       "RET",
+       "ROLB",
+       "ROLL",
+       "ROLW",
+       "RORB",
+       "RORL",
+       "RORW",
+       "SAHF",
+       "SALB",
+       "SALL",
+       "SALW",
+       "SARB",
+       "SARL",
+       "SARW",
+       "SBBB",
+       "SBBL",
+       "SBBW",
+       "SCASB",
+       "SCASL",
+       "SCASW",
+       "SETCC",
+       "SETCS",
+       "SETEQ",
+       "SETGE",
+       "SETGT",
+       "SETHI",
+       "SETLE",
+       "SETLS",
+       "SETLT",
+       "SETMI",
+       "SETNE",
+       "SETOC",
+       "SETOS",
+       "SETPC",
+       "SETPL",
+       "SETPS",
+       "CDQ",
+       "CWD",
+       "SHLB",
+       "SHLL",
+       "SHLW",
+       "SHRB",
+       "SHRL",
+       "SHRW",
+       "STC",
+       "STD",
+       "STI",
+       "STOSB",
+       "STOSL",
+       "STOSW",
+       "SUBB",
+       "SUBL",
+       "SUBW",
+       "SYSCALL",
+       "TESTB",
+       "TESTL",
+       "TESTW",
+       "TEXT",
+       "VERR",
+       "VERW",
+       "WAIT",
+       "WORD",
+       "XCHGB",
+       "XCHGL",
+       "XCHGW",
+       "XLAT",
+       "XORB",
+       "XORL",
+       "XORW",
+       "FMOVB",
+       "FMOVBP",
+       "FMOVD",
+       "FMOVDP",
+       "FMOVF",
+       "FMOVFP",
+       "FMOVL",
+       "FMOVLP",
+       "FMOVV",
+       "FMOVVP",
+       "FMOVW",
+       "FMOVWP",
+       "FMOVX",
+       "FMOVXP",
+       "FCOMB",
+       "FCOMBP",
+       "FCOMD",
+       "FCOMDP",
+       "FCOMDPP",
+       "FCOMF",
+       "FCOMFP",
+       "FCOML",
+       "FCOMLP",
+       "FCOMW",
+       "FCOMWP",
+       "FUCOM",
+       "FUCOMP",
+       "FUCOMPP",
+       "FADDDP",
+       "FADDW",
+       "FADDL",
+       "FADDF",
+       "FADDD",
+       "FMULDP",
+       "FMULW",
+       "FMULL",
+       "FMULF",
+       "FMULD",
+       "FSUBDP",
+       "FSUBW",
+       "FSUBL",
+       "FSUBF",
+       "FSUBD",
+       "FSUBRDP",
+       "FSUBRW",
+       "FSUBRL",
+       "FSUBRF",
+       "FSUBRD",
+       "FDIVDP",
+       "FDIVW",
+       "FDIVL",
+       "FDIVF",
+       "FDIVD",
+       "FDIVRDP",
+       "FDIVRW",
+       "FDIVRL",
+       "FDIVRF",
+       "FDIVRD",
+       "FXCHD",
+       "FFREE",
+       "FLDCW",
+       "FLDENV",
+       "FRSTOR",
+       "FSAVE",
+       "FSTCW",
+       "FSTENV",
+       "FSTSW",
+       "F2XM1",
+       "FABS",
+       "FCHS",
+       "FCLEX",
+       "FCOS",
+       "FDECSTP",
+       "FINCSTP",
+       "FINIT",
+       "FLD1",
+       "FLDL2E",
+       "FLDL2T",
+       "FLDLG2",
+       "FLDLN2",
+       "FLDPI",
+       "FLDZ",
+       "FNOP",
+       "FPATAN",
+       "FPREM",
+       "FPREM1",
+       "FPTAN",
+       "FRNDINT",
+       "FSCALE",
+       "FSIN",
+       "FSINCOS",
+       "FSQRT",
+       "FTST",
+       "FXAM",
+       "FXTRACT",
+       "FYL2X",
+       "FYL2XP1",
+       "END",
+       "DYNT_",
+       "INIT_",
+       "SIGNAME",
+       "CMPXCHGB",
+       "CMPXCHGL",
+       "CMPXCHGW",
+       "CMPXCHG8B",
+       "CPUID",
+       "INVD",
+       "INVLPG",
+       "LFENCE",
+       "MFENCE",
+       "MOVNTIL",
+       "RDMSR",
+       "RDPMC",
+       "RDTSC",
+       "RSM",
+       "SFENCE",
+       "SYSRET",
+       "WBINVD",
+       "WRMSR",
+       "XADDB",
+       "XADDL",
+       "XADDW",
+       "CMOVLCC",
+       "CMOVLCS",
+       "CMOVLEQ",
+       "CMOVLGE",
+       "CMOVLGT",
+       "CMOVLHI",
+       "CMOVLLE",
+       "CMOVLLS",
+       "CMOVLLT",
+       "CMOVLMI",
+       "CMOVLNE",
+       "CMOVLOC",
+       "CMOVLOS",
+       "CMOVLPC",
+       "CMOVLPL",
+       "CMOVLPS",
+       "CMOVQCC",
+       "CMOVQCS",
+       "CMOVQEQ",
+       "CMOVQGE",
+       "CMOVQGT",
+       "CMOVQHI",
+       "CMOVQLE",
+       "CMOVQLS",
+       "CMOVQLT",
+       "CMOVQMI",
+       "CMOVQNE",
+       "CMOVQOC",
+       "CMOVQOS",
+       "CMOVQPC",
+       "CMOVQPL",
+       "CMOVQPS",
+       "CMOVWCC",
+       "CMOVWCS",
+       "CMOVWEQ",
+       "CMOVWGE",
+       "CMOVWGT",
+       "CMOVWHI",
+       "CMOVWLE",
+       "CMOVWLS",
+       "CMOVWLT",
+       "CMOVWMI",
+       "CMOVWNE",
+       "CMOVWOC",
+       "CMOVWOS",
+       "CMOVWPC",
+       "CMOVWPL",
+       "CMOVWPS",
+       "ADCQ",
+       "ADDQ",
+       "ANDQ",
+       "BSFQ",
+       "BSRQ",
+       "BTCQ",
+       "BTQ",
+       "BTRQ",
+       "BTSQ",
+       "CMPQ",
+       "CMPSQ",
+       "CMPXCHGQ",
+       "CQO",
+       "DIVQ",
+       "IDIVQ",
+       "IMULQ",
+       "IRETQ",
+       "JCXZQ",
+       "LEAQ",
+       "LEAVEQ",
+       "LODSQ",
+       "MOVQ",
+       "MOVLQSX",
+       "MOVLQZX",
+       "MOVNTIQ",
+       "MOVSQ",
+       "MULQ",
+       "NEGQ",
+       "NOTQ",
+       "ORQ",
+       "POPFQ",
+       "POPQ",
+       "PUSHFQ",
+       "PUSHQ",
+       "RCLQ",
+       "RCRQ",
+       "ROLQ",
+       "RORQ",
+       "QUAD",
+       "SALQ",
+       "SARQ",
+       "SBBQ",
+       "SCASQ",
+       "SHLQ",
+       "SHRQ",
+       "STOSQ",
+       "SUBQ",
+       "TESTQ",
+       "XADDQ",
+       "XCHGQ",
+       "XORQ",
+       "ADDPD",
+       "ADDPS",
+       "ADDSD",
+       "ADDSS",
+       "ANDNPD",
+       "ANDNPS",
+       "ANDPD",
+       "ANDPS",
+       "CMPPD",
+       "CMPPS",
+       "CMPSD",
+       "CMPSS",
+       "COMISD",
+       "COMISS",
+       "CVTPD2PL",
+       "CVTPD2PS",
+       "CVTPL2PD",
+       "CVTPL2PS",
+       "CVTPS2PD",
+       "CVTPS2PL",
+       "CVTSD2SL",
+       "CVTSD2SQ",
+       "CVTSD2SS",
+       "CVTSL2SD",
+       "CVTSL2SS",
+       "CVTSQ2SD",
+       "CVTSQ2SS",
+       "CVTSS2SD",
+       "CVTSS2SL",
+       "CVTSS2SQ",
+       "CVTTPD2PL",
+       "CVTTPS2PL",
+       "CVTTSD2SL",
+       "CVTTSD2SQ",
+       "CVTTSS2SL",
+       "CVTTSS2SQ",
+       "DIVPD",
+       "DIVPS",
+       "DIVSD",
+       "DIVSS",
+       "EMMS",
+       "FXRSTOR",
+       "FXRSTOR64",
+       "FXSAVE",
+       "FXSAVE64",
+       "LDMXCSR",
+       "MASKMOVOU",
+       "MASKMOVQ",
+       "MAXPD",
+       "MAXPS",
+       "MAXSD",
+       "MAXSS",
+       "MINPD",
+       "MINPS",
+       "MINSD",
+       "MINSS",
+       "MOVAPD",
+       "MOVAPS",
+       "MOVOU",
+       "MOVHLPS",
+       "MOVHPD",
+       "MOVHPS",
+       "MOVLHPS",
+       "MOVLPD",
+       "MOVLPS",
+       "MOVMSKPD",
+       "MOVMSKPS",
+       "MOVNTO",
+       "MOVNTPD",
+       "MOVNTPS",
+       "MOVNTQ",
+       "MOVO",
+       "MOVQOZX",
+       "MOVSD",
+       "MOVSS",
+       "MOVUPD",
+       "MOVUPS",
+       "MULPD",
+       "MULPS",
+       "MULSD",
+       "MULSS",
+       "ORPD",
+       "ORPS",
+       "PACKSSLW",
+       "PACKSSWB",
+       "PACKUSWB",
+       "PADDB",
+       "PADDL",
+       "PADDQ",
+       "PADDSB",
+       "PADDSW",
+       "PADDUSB",
+       "PADDUSW",
+       "PADDW",
+       "PANDB",
+       "PANDL",
+       "PANDSB",
+       "PANDSW",
+       "PANDUSB",
+       "PANDUSW",
+       "PANDW",
+       "PAND",
+       "PANDN",
+       "PAVGB",
+       "PAVGW",
+       "PCMPEQB",
+       "PCMPEQL",
+       "PCMPEQW",
+       "PCMPGTB",
+       "PCMPGTL",
+       "PCMPGTW",
+       "PEXTRW",
+       "PFACC",
+       "PFADD",
+       "PFCMPEQ",
+       "PFCMPGE",
+       "PFCMPGT",
+       "PFMAX",
+       "PFMIN",
+       "PFMUL",
+       "PFNACC",
+       "PFPNACC",
+       "PFRCP",
+       "PFRCPIT1",
+       "PFRCPI2T",
+       "PFRSQIT1",
+       "PFRSQRT",
+       "PFSUB",
+       "PFSUBR",
+       "PINSRW",
+       "PINSRD",
+       "PINSRQ",
+       "PMADDWL",
+       "PMAXSW",
+       "PMAXUB",
+       "PMINSW",
+       "PMINUB",
+       "PMOVMSKB",
+       "PMULHRW",
+       "PMULHUW",
+       "PMULHW",
+       "PMULLW",
+       "PMULULQ",
+       "POR",
+       "PSADBW",
+       "PSHUFHW",
+       "PSHUFL",
+       "PSHUFLW",
+       "PSHUFW",
+       "PSHUFB",
+       "PSLLO",
+       "PSLLL",
+       "PSLLQ",
+       "PSLLW",
+       "PSRAL",
+       "PSRAW",
+       "PSRLO",
+       "PSRLL",
+       "PSRLQ",
+       "PSRLW",
+       "PSUBB",
+       "PSUBL",
+       "PSUBQ",
+       "PSUBSB",
+       "PSUBSW",
+       "PSUBUSB",
+       "PSUBUSW",
+       "PSUBW",
+       "PSWAPL",
+       "PUNPCKHBW",
+       "PUNPCKHLQ",
+       "PUNPCKHQDQ",
+       "PUNPCKHWL",
+       "PUNPCKLBW",
+       "PUNPCKLLQ",
+       "PUNPCKLQDQ",
+       "PUNPCKLWL",
+       "PXOR",
+       "RCPPS",
+       "RCPSS",
+       "RSQRTPS",
+       "RSQRTSS",
+       "SHUFPD",
+       "SHUFPS",
+       "SQRTPD",
+       "SQRTPS",
+       "SQRTSD",
+       "SQRTSS",
+       "STMXCSR",
+       "SUBPD",
+       "SUBPS",
+       "SUBSD",
+       "SUBSS",
+       "UCOMISD",
+       "UCOMISS",
+       "UNPCKHPD",
+       "UNPCKHPS",
+       "UNPCKLPD",
+       "UNPCKLPS",
+       "XORPD",
+       "XORPS",
+       "PF2IW",
+       "PF2IL",
+       "PI2FW",
+       "PI2FL",
+       "RETFW",
+       "RETFL",
+       "RETFQ",
+       "SWAPGS",
+       "MODE",
+       "CRC32B",
+       "CRC32Q",
+       "IMUL3Q",
+       "PREFETCHT0",
+       "PREFETCHT1",
+       "PREFETCHT2",
+       "PREFETCHNTA",
+       "MOVQL",
+       "BSWAPL",
+       "BSWAPQ",
+       "UNDEF",
+       "AESENC",
+       "AESENCLAST",
+       "AESDEC",
+       "AESDECLAST",
+       "AESIMC",
+       "AESKEYGENASSIST",
+       "PSHUFD",
+       "PCLMULQDQ",
+       "USEFIELD",
+       "TYPE",
+       "FUNCDATA",
+       "PCDATA",
+       "CHECKNIL",
+       "VARDEF",
+       "VARKILL",
+       "DUFFCOPY",
+       "DUFFZERO",
+       "LAST",
+}
+
+var dnames6 = []string{
+       D_AL:     "AL",
+       D_CL:     "CL",
+       D_DL:     "DL",
+       D_BL:     "BL",
+       D_SPB:    "SPB",
+       D_BPB:    "BPB",
+       D_SIB:    "SIB",
+       D_DIB:    "DIB",
+       D_R8B:    "R8B",
+       D_R9B:    "R9B",
+       D_R10B:   "R10B",
+       D_R11B:   "R11B",
+       D_R12B:   "R12B",
+       D_R13B:   "R13B",
+       D_R14B:   "R14B",
+       D_R15B:   "R15B",
+       D_AX:     "AX",
+       D_CX:     "CX",
+       D_DX:     "DX",
+       D_BX:     "BX",
+       D_SP:     "SP",
+       D_BP:     "BP",
+       D_SI:     "SI",
+       D_DI:     "DI",
+       D_R8:     "R8",
+       D_R9:     "R9",
+       D_R10:    "R10",
+       D_R11:    "R11",
+       D_R12:    "R12",
+       D_R13:    "R13",
+       D_R14:    "R14",
+       D_R15:    "R15",
+       D_AH:     "AH",
+       D_CH:     "CH",
+       D_DH:     "DH",
+       D_BH:     "BH",
+       D_F0:     "F0",
+       D_M0:     "M0",
+       D_X0:     "X0",
+       D_X1:     "X1",
+       D_X2:     "X2",
+       D_X3:     "X3",
+       D_X4:     "X4",
+       D_X5:     "X5",
+       D_X6:     "X6",
+       D_X7:     "X7",
+       D_X8:     "X8",
+       D_X9:     "X9",
+       D_X10:    "X10",
+       D_X11:    "X11",
+       D_X12:    "X12",
+       D_X13:    "X13",
+       D_X14:    "X14",
+       D_X15:    "X15",
+       D_CS:     "CS",
+       D_SS:     "SS",
+       D_DS:     "DS",
+       D_ES:     "ES",
+       D_FS:     "FS",
+       D_GS:     "GS",
+       D_GDTR:   "GDTR",
+       D_IDTR:   "IDTR",
+       D_LDTR:   "LDTR",
+       D_MSW:    "MSW",
+       D_TASK:   "TASK",
+       D_CR:     "CR",
+       D_DR:     "DR",
+       D_TR:     "TR",
+       D_TLS:    "TLS",
+       D_NONE:   "NONE",
+       D_BRANCH: "BRANCH",
+       D_EXTERN: "EXTERN",
+       D_STATIC: "STATIC",
+       D_AUTO:   "AUTO",
+       D_PARAM:  "PARAM",
+       D_CONST:  "CONST",
+       D_FCONST: "FCONST",
+       D_SCONST: "SCONST",
+       D_ADDR:   "ADDR",
+       D_INDIR:  "INDIR",
+}
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
new file mode 100644 (file)
index 0000000..0665a08
--- /dev/null
@@ -0,0 +1,4613 @@
+// Inferno utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.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.
+
+package x86
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+       "log"
+       "strings"
+)
+
+// Instruction layout.
+
+const (
+       MaxAlign   = 32
+       LoopAlign  = 16
+       MaxLoopPad = 0
+       FuncAlign  = 16
+)
+
+type Optab struct {
+       as     int16
+       ytab   []byte
+       prefix uint8
+       op     [23]uint8
+}
+
+type Movtab struct {
+       as   int16
+       ft   uint8
+       tt   uint8
+       code uint8
+       op   [4]uint8
+}
+
+const (
+       Yxxx = 0 + iota
+       Ynone
+       Yi0
+       Yi1
+       Yi8
+       Ys32
+       Yi32
+       Yi64
+       Yiauto
+       Yal
+       Ycl
+       Yax
+       Ycx
+       Yrb
+       Yrl
+       Yrf
+       Yf0
+       Yrx
+       Ymb
+       Yml
+       Ym
+       Ybr
+       Ycol
+       Ycs
+       Yss
+       Yds
+       Yes
+       Yfs
+       Ygs
+       Ygdtr
+       Yidtr
+       Yldtr
+       Ymsw
+       Ytask
+       Ycr0
+       Ycr1
+       Ycr2
+       Ycr3
+       Ycr4
+       Ycr5
+       Ycr6
+       Ycr7
+       Ycr8
+       Ydr0
+       Ydr1
+       Ydr2
+       Ydr3
+       Ydr4
+       Ydr5
+       Ydr6
+       Ydr7
+       Ytr0
+       Ytr1
+       Ytr2
+       Ytr3
+       Ytr4
+       Ytr5
+       Ytr6
+       Ytr7
+       Yrl32
+       Yrl64
+       Ymr
+       Ymm
+       Yxr
+       Yxm
+       Ytls
+       Ymax
+       Zxxx = 0 + iota - 67
+       Zlit
+       Zlitm_r
+       Z_rp
+       Zbr
+       Zcall
+       Zcallindreg
+       Zib_
+       Zib_rp
+       Zibo_m
+       Zibo_m_xm
+       Zil_
+       Zil_rp
+       Ziq_rp
+       Zilo_m
+       Ziqo_m
+       Zjmp
+       Zloop
+       Zo_iw
+       Zm_o
+       Zm_r
+       Zm2_r
+       Zm_r_xm
+       Zm_r_i_xm
+       Zm_r_3d
+       Zm_r_xm_nr
+       Zr_m_xm_nr
+       Zibm_r
+       Zmb_r
+       Zaut_r
+       Zo_m
+       Zo_m64
+       Zpseudo
+       Zr_m
+       Zr_m_xm
+       Zr_m_i_xm
+       Zrp_
+       Z_ib
+       Z_il
+       Zm_ibo
+       Zm_ilo
+       Zib_rr
+       Zil_rr
+       Zclr
+       Zbyte
+       Zmax
+       Px     = 0
+       P32    = 0x32
+       Pe     = 0x66
+       Pm     = 0x0f
+       Pq     = 0xff
+       Pb     = 0xfe
+       Pf2    = 0xf2
+       Pf3    = 0xf3
+       Pq3    = 0x67
+       Pw     = 0x48
+       Py     = 0x80
+       Rxf    = 1 << 9
+       Rxt    = 1 << 8
+       Rxw    = 1 << 3
+       Rxr    = 1 << 2
+       Rxx    = 1 << 1
+       Rxb    = 1 << 0
+       Maxand = 10
+)
+
+var ycover [Ymax * Ymax]uint8
+
+var reg [D_NONE]int
+
+var regrex [D_NONE + 1]int
+
+var ynone = []uint8{
+       Ynone,
+       Ynone,
+       Zlit,
+       1,
+       0,
+}
+
+var ytext = []uint8{
+       Ymb,
+       Yi64,
+       Zpseudo,
+       1,
+       0,
+}
+
+var ynop = []uint8{
+       Ynone,
+       Ynone,
+       Zpseudo,
+       0,
+       Ynone,
+       Yiauto,
+       Zpseudo,
+       0,
+       Ynone,
+       Yml,
+       Zpseudo,
+       0,
+       Ynone,
+       Yrf,
+       Zpseudo,
+       0,
+       Ynone,
+       Yxr,
+       Zpseudo,
+       0,
+       Yiauto,
+       Ynone,
+       Zpseudo,
+       0,
+       Yml,
+       Ynone,
+       Zpseudo,
+       0,
+       Yrf,
+       Ynone,
+       Zpseudo,
+       0,
+       Yxr,
+       Ynone,
+       Zpseudo,
+       1,
+       0,
+}
+
+var yfuncdata = []uint8{
+       Yi32,
+       Ym,
+       Zpseudo,
+       0,
+       0,
+}
+
+var ypcdata = []uint8{
+       Yi32,
+       Yi32,
+       Zpseudo,
+       0,
+       0,
+}
+
+var yxorb = []uint8{
+       Yi32,
+       Yal,
+       Zib_,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var yxorl = []uint8{
+       Yi8,
+       Yml,
+       Zibo_m,
+       2,
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yaddl = []uint8{
+       Yi8,
+       Yml,
+       Zibo_m,
+       2,
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yincb = []uint8{
+       Ynone,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yincw = []uint8{
+       Ynone,
+       Yml,
+       Zo_m,
+       2,
+       0,
+}
+
+var yincl = []uint8{
+       Ynone,
+       Yml,
+       Zo_m,
+       2,
+       0,
+}
+
+var ycmpb = []uint8{
+       Yal,
+       Yi32,
+       Z_ib,
+       1,
+       Ymb,
+       Yi32,
+       Zm_ibo,
+       2,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       0,
+}
+
+var ycmpl = []uint8{
+       Yml,
+       Yi8,
+       Zm_ibo,
+       2,
+       Yax,
+       Yi32,
+       Z_il,
+       1,
+       Yml,
+       Yi32,
+       Zm_ilo,
+       2,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       0,
+}
+
+var yshb = []uint8{
+       Yi1,
+       Ymb,
+       Zo_m,
+       2,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Ycx,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yshl = []uint8{
+       Yi1,
+       Yml,
+       Zo_m,
+       2,
+       Yi32,
+       Yml,
+       Zibo_m,
+       2,
+       Ycl,
+       Yml,
+       Zo_m,
+       2,
+       Ycx,
+       Yml,
+       Zo_m,
+       2,
+       0,
+}
+
+var ytestb = []uint8{
+       Yi32,
+       Yal,
+       Zib_,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var ytestl = []uint8{
+       Yi32,
+       Yax,
+       Zil_,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var ymovb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       Yi32,
+       Yrb,
+       Zib_rp,
+       1,
+       Yi32,
+       Ymb,
+       Zibo_m,
+       2,
+       0,
+}
+
+var ymbs = []uint8{
+       Ymb,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ybtl = []uint8{
+       Yi8,
+       Yml,
+       Zibo_m,
+       2,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       0,
+}
+
+var ymovw = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yi0,
+       Yrl,
+       Zclr,
+       1,
+       Yi32,
+       Yrl,
+       Zil_rp,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yiauto,
+       Yrl,
+       Zaut_r,
+       2,
+       0,
+}
+
+var ymovl = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       Yi0,
+       Yrl,
+       Zclr,
+       1,
+       Yi32,
+       Yrl,
+       Zil_rp,
+       1,
+       Yi32,
+       Yml,
+       Zilo_m,
+       2,
+       Yml,
+       Ymr,
+       Zm_r_xm,
+       1, // MMX MOVD
+       Ymr,
+       Yml,
+       Zr_m_xm,
+       1, // MMX MOVD
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       2, // XMM MOVD (32 bit)
+       Yxr,
+       Yml,
+       Zr_m_xm,
+       2, // XMM MOVD (32 bit)
+       Yiauto,
+       Yrl,
+       Zaut_r,
+       2,
+       0,
+}
+
+var yret = []uint8{
+       Ynone,
+       Ynone,
+       Zo_iw,
+       1,
+       Yi32,
+       Ynone,
+       Zo_iw,
+       1,
+       0,
+}
+
+var ymovq = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1, // 0x89
+       Yml,
+       Yrl,
+       Zm_r,
+       1, // 0x8b
+       Yi0,
+       Yrl,
+       Zclr,
+       1, // 0x31
+       Ys32,
+       Yrl,
+       Zilo_m,
+       2, // 32 bit signed 0xc7,(0)
+       Yi64,
+       Yrl,
+       Ziq_rp,
+       1, // 0xb8 -- 32/64 bit immediate
+       Yi32,
+       Yml,
+       Zilo_m,
+       2, // 0xc7,(0)
+       Ym,
+       Ymr,
+       Zm_r_xm_nr,
+       1, // MMX MOVQ (shorter encoding)
+       Ymr,
+       Ym,
+       Zr_m_xm_nr,
+       1, // MMX MOVQ
+       Ymm,
+       Ymr,
+       Zm_r_xm,
+       1, // MMX MOVD
+       Ymr,
+       Ymm,
+       Zr_m_xm,
+       1, // MMX MOVD
+       Yxr,
+       Ymr,
+       Zm_r_xm_nr,
+       2, // MOVDQ2Q
+       Yxm,
+       Yxr,
+       Zm_r_xm_nr,
+       2, // MOVQ xmm1/m64 -> xmm2
+       Yxr,
+       Yxm,
+       Zr_m_xm_nr,
+       2, // MOVQ xmm1 -> xmm2/m64
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       2, // MOVD xmm load
+       Yxr,
+       Yml,
+       Zr_m_xm,
+       2, // MOVD xmm store
+       Yiauto,
+       Yrl,
+       Zaut_r,
+       2, // built-in LEAQ
+       0,
+}
+
+var ym_rl = []uint8{
+       Ym,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yrl_m = []uint8{
+       Yrl,
+       Ym,
+       Zr_m,
+       1,
+       0,
+}
+
+var ymb_rl = []uint8{
+       Ymb,
+       Yrl,
+       Zmb_r,
+       1,
+       0,
+}
+
+var yml_rl = []uint8{
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var yrl_ml = []uint8{
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       0,
+}
+
+var yml_mb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       Ymb,
+       Yrb,
+       Zm_r,
+       1,
+       0,
+}
+
+var yrb_mb = []uint8{
+       Yrb,
+       Ymb,
+       Zr_m,
+       1,
+       0,
+}
+
+var yxchg = []uint8{
+       Yax,
+       Yrl,
+       Z_rp,
+       1,
+       Yrl,
+       Yax,
+       Zrp_,
+       1,
+       Yrl,
+       Yml,
+       Zr_m,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var ydivl = []uint8{
+       Yml,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ydivb = []uint8{
+       Ymb,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var yimul = []uint8{
+       Yml,
+       Ynone,
+       Zm_o,
+       2,
+       Yi8,
+       Yrl,
+       Zib_rr,
+       1,
+       Yi32,
+       Yrl,
+       Zil_rr,
+       1,
+       Yml,
+       Yrl,
+       Zm_r,
+       2,
+       0,
+}
+
+var yimul3 = []uint8{
+       Yml,
+       Yrl,
+       Zibm_r,
+       2,
+       0,
+}
+
+var ybyte = []uint8{
+       Yi64,
+       Ynone,
+       Zbyte,
+       1,
+       0,
+}
+
+var yin = []uint8{
+       Yi32,
+       Ynone,
+       Zib_,
+       1,
+       Ynone,
+       Ynone,
+       Zlit,
+       1,
+       0,
+}
+
+var yint = []uint8{
+       Yi32,
+       Ynone,
+       Zib_,
+       1,
+       0,
+}
+
+var ypushl = []uint8{
+       Yrl,
+       Ynone,
+       Zrp_,
+       1,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       Yi8,
+       Ynone,
+       Zib_,
+       1,
+       Yi32,
+       Ynone,
+       Zil_,
+       1,
+       0,
+}
+
+var ypopl = []uint8{
+       Ynone,
+       Yrl,
+       Z_rp,
+       1,
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var ybswap = []uint8{
+       Ynone,
+       Yrl,
+       Z_rp,
+       2,
+       0,
+}
+
+var yscond = []uint8{
+       Ynone,
+       Ymb,
+       Zo_m,
+       2,
+       0,
+}
+
+var yjcond = []uint8{
+       Ynone,
+       Ybr,
+       Zbr,
+       0,
+       Yi0,
+       Ybr,
+       Zbr,
+       0,
+       Yi1,
+       Ybr,
+       Zbr,
+       1,
+       0,
+}
+
+var yloop = []uint8{
+       Ynone,
+       Ybr,
+       Zloop,
+       1,
+       0,
+}
+
+var ycall = []uint8{
+       Ynone,
+       Yml,
+       Zcallindreg,
+       0,
+       Yrx,
+       Yrx,
+       Zcallindreg,
+       2,
+       Ynone,
+       Ybr,
+       Zcall,
+       1,
+       0,
+}
+
+var yduff = []uint8{
+       Ynone,
+       Yi32,
+       Zcall,
+       1,
+       0,
+}
+
+var yjmp = []uint8{
+       Ynone,
+       Yml,
+       Zo_m64,
+       2,
+       Ynone,
+       Ybr,
+       Zjmp,
+       1,
+       0,
+}
+
+var yfmvd = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvdp = []uint8{
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvf = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfmvx = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       0,
+}
+
+var yfmvp = []uint8{
+       Yf0,
+       Ym,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfadd = []uint8{
+       Ym,
+       Yf0,
+       Zm_o,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfaddp = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       0,
+}
+
+var yfxch = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2,
+       Yrf,
+       Yf0,
+       Zm_o,
+       2,
+       0,
+}
+
+var ycompp = []uint8{
+       Yf0,
+       Yrf,
+       Zo_m,
+       2, /* botch is really f0,f1 */
+       0,
+}
+
+var ystsw = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ynone,
+       Yax,
+       Zlit,
+       1,
+       0,
+}
+
+var ystcw = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ysvrs = []uint8{
+       Ynone,
+       Ym,
+       Zo_m,
+       2,
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var ymm = []uint8{
+       Ymm,
+       Ymr,
+       Zm_r_xm,
+       1,
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxm = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcvm1 = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       Yxm,
+       Ymr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxcvm2 = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       Ymm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+/*
+static uchar   yxmq[] =
+{
+       Yxm,    Yxr,    Zm_r_xm,        2,
+       0
+};
+*/
+var yxr = []uint8{
+       Yxr,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxr_ml = []uint8{
+       Yxr,
+       Yml,
+       Zr_m_xm,
+       1,
+       0,
+}
+
+var ymr = []uint8{
+       Ymr,
+       Ymr,
+       Zm_r,
+       1,
+       0,
+}
+
+var ymr_ml = []uint8{
+       Ymr,
+       Yml,
+       Zr_m_xm,
+       1,
+       0,
+}
+
+var yxcmp = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcmpi = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_i_xm,
+       2,
+       0,
+}
+
+var yxmov = []uint8{
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       Yxr,
+       Yxm,
+       Zr_m_xm,
+       1,
+       0,
+}
+
+var yxcvfl = []uint8{
+       Yxm,
+       Yrl,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcvlf = []uint8{
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var yxcvfq = []uint8{
+       Yxm,
+       Yrl,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yxcvqf = []uint8{
+       Yml,
+       Yxr,
+       Zm_r_xm,
+       2,
+       0,
+}
+
+var yps = []uint8{
+       Ymm,
+       Ymr,
+       Zm_r_xm,
+       1,
+       Yi8,
+       Ymr,
+       Zibo_m_xm,
+       2,
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       2,
+       Yi8,
+       Yxr,
+       Zibo_m_xm,
+       3,
+       0,
+}
+
+var yxrrl = []uint8{
+       Yxr,
+       Yrl,
+       Zm_r,
+       1,
+       0,
+}
+
+var ymfp = []uint8{
+       Ymm,
+       Ymr,
+       Zm_r_3d,
+       1,
+       0,
+}
+
+var ymrxr = []uint8{
+       Ymr,
+       Yxr,
+       Zm_r,
+       1,
+       Yxm,
+       Yxr,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var ymshuf = []uint8{
+       Ymm,
+       Ymr,
+       Zibm_r,
+       2,
+       0,
+}
+
+var ymshufb = []uint8{
+       Yxm,
+       Yxr,
+       Zm2_r,
+       2,
+       0,
+}
+
+var yxshuf = []uint8{
+       Yxm,
+       Yxr,
+       Zibm_r,
+       2,
+       0,
+}
+
+var yextrw = []uint8{
+       Yxr,
+       Yrl,
+       Zibm_r,
+       2,
+       0,
+}
+
+var yinsrw = []uint8{
+       Yml,
+       Yxr,
+       Zibm_r,
+       2,
+       0,
+}
+
+var yinsr = []uint8{
+       Ymm,
+       Yxr,
+       Zibm_r,
+       3,
+       0,
+}
+
+var ypsdq = []uint8{
+       Yi8,
+       Yxr,
+       Zibo_m,
+       2,
+       0,
+}
+
+var ymskb = []uint8{
+       Yxr,
+       Yrl,
+       Zm_r_xm,
+       2,
+       Ymr,
+       Yrl,
+       Zm_r_xm,
+       1,
+       0,
+}
+
+var ycrc32l = []uint8{Yml, Yrl, Zlitm_r, 0}
+
+var yprefetch = []uint8{
+       Ym,
+       Ynone,
+       Zm_o,
+       2,
+       0,
+}
+
+var yaes = []uint8{
+       Yxm,
+       Yxr,
+       Zlitm_r,
+       2,
+       0,
+}
+
+var yaes2 = []uint8{
+       Yxm,
+       Yxr,
+       Zibm_r,
+       2,
+       0,
+}
+
+/*
+ * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32,
+ * and p->from and p->to as operands (Addr*).  The linker scans optab to find
+ * the entry with the given p->as and then looks through the ytable for that
+ * instruction (the second field in the optab struct) for a line whose first
+ * two values match the Ytypes of the p->from and p->to operands.  The function
+ * oclass in span.c computes the specific Ytype of an operand and then the set
+ * of more general Ytypes that it satisfies is implied by the ycover table, set
+ * up in instinit.  For example, oclass distinguishes the constants 0 and 1
+ * from the more general 8-bit constants, but instinit says
+ *
+ *        ycover[Yi0*Ymax + Ys32] = 1;
+ *        ycover[Yi1*Ymax + Ys32] = 1;
+ *        ycover[Yi8*Ymax + Ys32] = 1;
+ *
+ * which means that Yi0, Yi1, and Yi8 all count as Ys32 (signed 32)
+ * if that's what an instruction can handle.
+ *
+ * In parallel with the scan through the ytable for the appropriate line, there
+ * is a z pointer that starts out pointing at the strange magic byte list in
+ * the Optab struct.  With each step past a non-matching ytable line, z
+ * advances by the 4th entry in the line.  When a matching line is found, that
+ * z pointer has the extra data to use in laying down the instruction bytes.
+ * The actual bytes laid down are a function of the 3rd entry in the line (that
+ * is, the Ztype) and the z bytes.
+ *
+ * For example, let's look at AADDL.  The optab line says:
+ *        { AADDL,        yaddl,  Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
+ *
+ * and yaddl says
+ *        uchar   yaddl[] =
+ *        {
+ *                Yi8,    Yml,    Zibo_m, 2,
+ *                Yi32,   Yax,    Zil_,   1,
+ *                Yi32,   Yml,    Zilo_m, 2,
+ *                Yrl,    Yml,    Zr_m,   1,
+ *                Yml,    Yrl,    Zm_r,   1,
+ *                0
+ *        };
+ *
+ * so there are 5 possible types of ADDL instruction that can be laid down, and
+ * possible states used to lay them down (Ztype and z pointer, assuming z
+ * points at {0x83,(00),0x05,0x81,(00),0x01,0x03}) are:
+ *
+ *        Yi8, Yml -> Zibo_m, z (0x83, 00)
+ *        Yi32, Yax -> Zil_, z+2 (0x05)
+ *        Yi32, Yml -> Zilo_m, z+2+1 (0x81, 0x00)
+ *        Yrl, Yml -> Zr_m, z+2+1+2 (0x01)
+ *        Yml, Yrl -> Zm_r, z+2+1+2+1 (0x03)
+ *
+ * The Pconstant in the optab line controls the prefix bytes to emit.  That's
+ * relatively straightforward as this program goes.
+ *
+ * The switch on t[2] in doasm implements the various Z cases.  Zibo_m, for
+ * example, is an opcode byte (z[0]) then an asmando (which is some kind of
+ * encoded addressing mode for the Yml arg), and then a single immediate byte.
+ * Zilo_m is the same but a long (32-bit) immediate.
+ */
+var optab =
+/*     as, ytab, andproto, opcode */
+[]Optab{
+       Optab{AXXX, nil, 0, [23]uint8{}},
+       Optab{AAAA, ynone, P32, [23]uint8{0x37}},
+       Optab{AAAD, ynone, P32, [23]uint8{0xd5, 0x0a}},
+       Optab{AAAM, ynone, P32, [23]uint8{0xd4, 0x0a}},
+       Optab{AAAS, ynone, P32, [23]uint8{0x3f}},
+       Optab{AADCB, yxorb, Pb, [23]uint8{0x14, 0x80, 02, 0x10, 0x10}},
+       Optab{AADCL, yxorl, Px, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+       Optab{AADCQ, yxorl, Pw, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+       Optab{AADCW, yxorl, Pe, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+       Optab{AADDB, yxorb, Pb, [23]uint8{0x04, 0x80, 00, 0x00, 0x02}},
+       Optab{AADDL, yaddl, Px, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+       Optab{AADDPD, yxm, Pq, [23]uint8{0x58}},
+       Optab{AADDPS, yxm, Pm, [23]uint8{0x58}},
+       Optab{AADDQ, yaddl, Pw, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+       Optab{AADDSD, yxm, Pf2, [23]uint8{0x58}},
+       Optab{AADDSS, yxm, Pf3, [23]uint8{0x58}},
+       Optab{AADDW, yaddl, Pe, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+       Optab{AADJSP, nil, 0, [23]uint8{}},
+       Optab{AANDB, yxorb, Pb, [23]uint8{0x24, 0x80, 04, 0x20, 0x22}},
+       Optab{AANDL, yxorl, Px, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+       Optab{AANDNPD, yxm, Pq, [23]uint8{0x55}},
+       Optab{AANDNPS, yxm, Pm, [23]uint8{0x55}},
+       Optab{AANDPD, yxm, Pq, [23]uint8{0x54}},
+       Optab{AANDPS, yxm, Pq, [23]uint8{0x54}},
+       Optab{AANDQ, yxorl, Pw, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+       Optab{AANDW, yxorl, Pe, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+       Optab{AARPL, yrl_ml, P32, [23]uint8{0x63}},
+       Optab{ABOUNDL, yrl_m, P32, [23]uint8{0x62}},
+       Optab{ABOUNDW, yrl_m, Pe, [23]uint8{0x62}},
+       Optab{ABSFL, yml_rl, Pm, [23]uint8{0xbc}},
+       Optab{ABSFQ, yml_rl, Pw, [23]uint8{0x0f, 0xbc}},
+       Optab{ABSFW, yml_rl, Pq, [23]uint8{0xbc}},
+       Optab{ABSRL, yml_rl, Pm, [23]uint8{0xbd}},
+       Optab{ABSRQ, yml_rl, Pw, [23]uint8{0x0f, 0xbd}},
+       Optab{ABSRW, yml_rl, Pq, [23]uint8{0xbd}},
+       Optab{ABSWAPL, ybswap, Px, [23]uint8{0x0f, 0xc8}},
+       Optab{ABSWAPQ, ybswap, Pw, [23]uint8{0x0f, 0xc8}},
+       Optab{ABTCL, ybtl, Pm, [23]uint8{0xba, 07, 0xbb}},
+       Optab{ABTCQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 07, 0x0f, 0xbb}},
+       Optab{ABTCW, ybtl, Pq, [23]uint8{0xba, 07, 0xbb}},
+       Optab{ABTL, ybtl, Pm, [23]uint8{0xba, 04, 0xa3}},
+       Optab{ABTQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 04, 0x0f, 0xa3}},
+       Optab{ABTRL, ybtl, Pm, [23]uint8{0xba, 06, 0xb3}},
+       Optab{ABTRQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 06, 0x0f, 0xb3}},
+       Optab{ABTRW, ybtl, Pq, [23]uint8{0xba, 06, 0xb3}},
+       Optab{ABTSL, ybtl, Pm, [23]uint8{0xba, 05, 0xab}},
+       Optab{ABTSQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 05, 0x0f, 0xab}},
+       Optab{ABTSW, ybtl, Pq, [23]uint8{0xba, 05, 0xab}},
+       Optab{ABTW, ybtl, Pq, [23]uint8{0xba, 04, 0xa3}},
+       Optab{ABYTE, ybyte, Px, [23]uint8{1}},
+       Optab{ACALL, ycall, Px, [23]uint8{0xff, 02, 0xe8}},
+       Optab{ACDQ, ynone, Px, [23]uint8{0x99}},
+       Optab{ACLC, ynone, Px, [23]uint8{0xf8}},
+       Optab{ACLD, ynone, Px, [23]uint8{0xfc}},
+       Optab{ACLI, ynone, Px, [23]uint8{0xfa}},
+       Optab{ACLTS, ynone, Pm, [23]uint8{0x06}},
+       Optab{ACMC, ynone, Px, [23]uint8{0xf5}},
+       Optab{ACMOVLCC, yml_rl, Pm, [23]uint8{0x43}},
+       Optab{ACMOVLCS, yml_rl, Pm, [23]uint8{0x42}},
+       Optab{ACMOVLEQ, yml_rl, Pm, [23]uint8{0x44}},
+       Optab{ACMOVLGE, yml_rl, Pm, [23]uint8{0x4d}},
+       Optab{ACMOVLGT, yml_rl, Pm, [23]uint8{0x4f}},
+       Optab{ACMOVLHI, yml_rl, Pm, [23]uint8{0x47}},
+       Optab{ACMOVLLE, yml_rl, Pm, [23]uint8{0x4e}},
+       Optab{ACMOVLLS, yml_rl, Pm, [23]uint8{0x46}},
+       Optab{ACMOVLLT, yml_rl, Pm, [23]uint8{0x4c}},
+       Optab{ACMOVLMI, yml_rl, Pm, [23]uint8{0x48}},
+       Optab{ACMOVLNE, yml_rl, Pm, [23]uint8{0x45}},
+       Optab{ACMOVLOC, yml_rl, Pm, [23]uint8{0x41}},
+       Optab{ACMOVLOS, yml_rl, Pm, [23]uint8{0x40}},
+       Optab{ACMOVLPC, yml_rl, Pm, [23]uint8{0x4b}},
+       Optab{ACMOVLPL, yml_rl, Pm, [23]uint8{0x49}},
+       Optab{ACMOVLPS, yml_rl, Pm, [23]uint8{0x4a}},
+       Optab{ACMOVQCC, yml_rl, Pw, [23]uint8{0x0f, 0x43}},
+       Optab{ACMOVQCS, yml_rl, Pw, [23]uint8{0x0f, 0x42}},
+       Optab{ACMOVQEQ, yml_rl, Pw, [23]uint8{0x0f, 0x44}},
+       Optab{ACMOVQGE, yml_rl, Pw, [23]uint8{0x0f, 0x4d}},
+       Optab{ACMOVQGT, yml_rl, Pw, [23]uint8{0x0f, 0x4f}},
+       Optab{ACMOVQHI, yml_rl, Pw, [23]uint8{0x0f, 0x47}},
+       Optab{ACMOVQLE, yml_rl, Pw, [23]uint8{0x0f, 0x4e}},
+       Optab{ACMOVQLS, yml_rl, Pw, [23]uint8{0x0f, 0x46}},
+       Optab{ACMOVQLT, yml_rl, Pw, [23]uint8{0x0f, 0x4c}},
+       Optab{ACMOVQMI, yml_rl, Pw, [23]uint8{0x0f, 0x48}},
+       Optab{ACMOVQNE, yml_rl, Pw, [23]uint8{0x0f, 0x45}},
+       Optab{ACMOVQOC, yml_rl, Pw, [23]uint8{0x0f, 0x41}},
+       Optab{ACMOVQOS, yml_rl, Pw, [23]uint8{0x0f, 0x40}},
+       Optab{ACMOVQPC, yml_rl, Pw, [23]uint8{0x0f, 0x4b}},
+       Optab{ACMOVQPL, yml_rl, Pw, [23]uint8{0x0f, 0x49}},
+       Optab{ACMOVQPS, yml_rl, Pw, [23]uint8{0x0f, 0x4a}},
+       Optab{ACMOVWCC, yml_rl, Pq, [23]uint8{0x43}},
+       Optab{ACMOVWCS, yml_rl, Pq, [23]uint8{0x42}},
+       Optab{ACMOVWEQ, yml_rl, Pq, [23]uint8{0x44}},
+       Optab{ACMOVWGE, yml_rl, Pq, [23]uint8{0x4d}},
+       Optab{ACMOVWGT, yml_rl, Pq, [23]uint8{0x4f}},
+       Optab{ACMOVWHI, yml_rl, Pq, [23]uint8{0x47}},
+       Optab{ACMOVWLE, yml_rl, Pq, [23]uint8{0x4e}},
+       Optab{ACMOVWLS, yml_rl, Pq, [23]uint8{0x46}},
+       Optab{ACMOVWLT, yml_rl, Pq, [23]uint8{0x4c}},
+       Optab{ACMOVWMI, yml_rl, Pq, [23]uint8{0x48}},
+       Optab{ACMOVWNE, yml_rl, Pq, [23]uint8{0x45}},
+       Optab{ACMOVWOC, yml_rl, Pq, [23]uint8{0x41}},
+       Optab{ACMOVWOS, yml_rl, Pq, [23]uint8{0x40}},
+       Optab{ACMOVWPC, yml_rl, Pq, [23]uint8{0x4b}},
+       Optab{ACMOVWPL, yml_rl, Pq, [23]uint8{0x49}},
+       Optab{ACMOVWPS, yml_rl, Pq, [23]uint8{0x4a}},
+       Optab{ACMPB, ycmpb, Pb, [23]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
+       Optab{ACMPL, ycmpl, Px, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+       Optab{ACMPPD, yxcmpi, Px, [23]uint8{Pe, 0xc2}},
+       Optab{ACMPPS, yxcmpi, Pm, [23]uint8{0xc2, 0}},
+       Optab{ACMPQ, ycmpl, Pw, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+       Optab{ACMPSB, ynone, Pb, [23]uint8{0xa6}},
+       Optab{ACMPSD, yxcmpi, Px, [23]uint8{Pf2, 0xc2}},
+       Optab{ACMPSL, ynone, Px, [23]uint8{0xa7}},
+       Optab{ACMPSQ, ynone, Pw, [23]uint8{0xa7}},
+       Optab{ACMPSS, yxcmpi, Px, [23]uint8{Pf3, 0xc2}},
+       Optab{ACMPSW, ynone, Pe, [23]uint8{0xa7}},
+       Optab{ACMPW, ycmpl, Pe, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+       Optab{ACOMISD, yxcmp, Pe, [23]uint8{0x2f}},
+       Optab{ACOMISS, yxcmp, Pm, [23]uint8{0x2f}},
+       Optab{ACPUID, ynone, Pm, [23]uint8{0xa2}},
+       Optab{ACVTPL2PD, yxcvm2, Px, [23]uint8{Pf3, 0xe6, Pe, 0x2a}},
+       Optab{ACVTPL2PS, yxcvm2, Pm, [23]uint8{0x5b, 0, 0x2a, 0}},
+       Optab{ACVTPD2PL, yxcvm1, Px, [23]uint8{Pf2, 0xe6, Pe, 0x2d}},
+       Optab{ACVTPD2PS, yxm, Pe, [23]uint8{0x5a}},
+       Optab{ACVTPS2PL, yxcvm1, Px, [23]uint8{Pe, 0x5b, Pm, 0x2d}},
+       Optab{ACVTPS2PD, yxm, Pm, [23]uint8{0x5a}},
+       Optab{API2FW, ymfp, Px, [23]uint8{0x0c}},
+       Optab{ACVTSD2SL, yxcvfl, Pf2, [23]uint8{0x2d}},
+       Optab{ACVTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2d}},
+       Optab{ACVTSD2SS, yxm, Pf2, [23]uint8{0x5a}},
+       Optab{ACVTSL2SD, yxcvlf, Pf2, [23]uint8{0x2a}},
+       Optab{ACVTSQ2SD, yxcvqf, Pw, [23]uint8{Pf2, 0x2a}},
+       Optab{ACVTSL2SS, yxcvlf, Pf3, [23]uint8{0x2a}},
+       Optab{ACVTSQ2SS, yxcvqf, Pw, [23]uint8{Pf3, 0x2a}},
+       Optab{ACVTSS2SD, yxm, Pf3, [23]uint8{0x5a}},
+       Optab{ACVTSS2SL, yxcvfl, Pf3, [23]uint8{0x2d}},
+       Optab{ACVTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2d}},
+       Optab{ACVTTPD2PL, yxcvm1, Px, [23]uint8{Pe, 0xe6, Pe, 0x2c}},
+       Optab{ACVTTPS2PL, yxcvm1, Px, [23]uint8{Pf3, 0x5b, Pm, 0x2c}},
+       Optab{ACVTTSD2SL, yxcvfl, Pf2, [23]uint8{0x2c}},
+       Optab{ACVTTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2c}},
+       Optab{ACVTTSS2SL, yxcvfl, Pf3, [23]uint8{0x2c}},
+       Optab{ACVTTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2c}},
+       Optab{ACWD, ynone, Pe, [23]uint8{0x99}},
+       Optab{ACQO, ynone, Pw, [23]uint8{0x99}},
+       Optab{ADAA, ynone, P32, [23]uint8{0x27}},
+       Optab{ADAS, ynone, P32, [23]uint8{0x2f}},
+       Optab{ADATA, nil, 0, [23]uint8{}},
+       Optab{ADECB, yincb, Pb, [23]uint8{0xfe, 01}},
+       Optab{ADECL, yincl, Px, [23]uint8{0xff, 01}},
+       Optab{ADECQ, yincl, Pw, [23]uint8{0xff, 01}},
+       Optab{ADECW, yincw, Pe, [23]uint8{0xff, 01}},
+       Optab{ADIVB, ydivb, Pb, [23]uint8{0xf6, 06}},
+       Optab{ADIVL, ydivl, Px, [23]uint8{0xf7, 06}},
+       Optab{ADIVPD, yxm, Pe, [23]uint8{0x5e}},
+       Optab{ADIVPS, yxm, Pm, [23]uint8{0x5e}},
+       Optab{ADIVQ, ydivl, Pw, [23]uint8{0xf7, 06}},
+       Optab{ADIVSD, yxm, Pf2, [23]uint8{0x5e}},
+       Optab{ADIVSS, yxm, Pf3, [23]uint8{0x5e}},
+       Optab{ADIVW, ydivl, Pe, [23]uint8{0xf7, 06}},
+       Optab{AEMMS, ynone, Pm, [23]uint8{0x77}},
+       Optab{AENTER, nil, 0, [23]uint8{}}, /* botch */
+       Optab{AFXRSTOR, ysvrs, Pm, [23]uint8{0xae, 01, 0xae, 01}},
+       Optab{AFXSAVE, ysvrs, Pm, [23]uint8{0xae, 00, 0xae, 00}},
+       Optab{AFXRSTOR64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 01, 0x0f, 0xae, 01}},
+       Optab{AFXSAVE64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 00, 0x0f, 0xae, 00}},
+       Optab{AGLOBL, nil, 0, [23]uint8{}},
+       Optab{AGOK, nil, 0, [23]uint8{}},
+       Optab{AHISTORY, nil, 0, [23]uint8{}},
+       Optab{AHLT, ynone, Px, [23]uint8{0xf4}},
+       Optab{AIDIVB, ydivb, Pb, [23]uint8{0xf6, 07}},
+       Optab{AIDIVL, ydivl, Px, [23]uint8{0xf7, 07}},
+       Optab{AIDIVQ, ydivl, Pw, [23]uint8{0xf7, 07}},
+       Optab{AIDIVW, ydivl, Pe, [23]uint8{0xf7, 07}},
+       Optab{AIMULB, ydivb, Pb, [23]uint8{0xf6, 05}},
+       Optab{AIMULL, yimul, Px, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+       Optab{AIMULQ, yimul, Pw, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+       Optab{AIMULW, yimul, Pe, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+       Optab{AIMUL3Q, yimul3, Pw, [23]uint8{0x6b, 00}},
+       Optab{AINB, yin, Pb, [23]uint8{0xe4, 0xec}},
+       Optab{AINCB, yincb, Pb, [23]uint8{0xfe, 00}},
+       Optab{AINCL, yincl, Px, [23]uint8{0xff, 00}},
+       Optab{AINCQ, yincl, Pw, [23]uint8{0xff, 00}},
+       Optab{AINCW, yincw, Pe, [23]uint8{0xff, 00}},
+       Optab{AINL, yin, Px, [23]uint8{0xe5, 0xed}},
+       Optab{AINSB, ynone, Pb, [23]uint8{0x6c}},
+       Optab{AINSL, ynone, Px, [23]uint8{0x6d}},
+       Optab{AINSW, ynone, Pe, [23]uint8{0x6d}},
+       Optab{AINT, yint, Px, [23]uint8{0xcd}},
+       Optab{AINTO, ynone, P32, [23]uint8{0xce}},
+       Optab{AINW, yin, Pe, [23]uint8{0xe5, 0xed}},
+       Optab{AIRETL, ynone, Px, [23]uint8{0xcf}},
+       Optab{AIRETQ, ynone, Pw, [23]uint8{0xcf}},
+       Optab{AIRETW, ynone, Pe, [23]uint8{0xcf}},
+       Optab{AJCC, yjcond, Px, [23]uint8{0x73, 0x83, 00}},
+       Optab{AJCS, yjcond, Px, [23]uint8{0x72, 0x82}},
+       Optab{AJCXZL, yloop, Px, [23]uint8{0xe3}},
+       Optab{AJCXZQ, yloop, Px, [23]uint8{0xe3}},
+       Optab{AJEQ, yjcond, Px, [23]uint8{0x74, 0x84}},
+       Optab{AJGE, yjcond, Px, [23]uint8{0x7d, 0x8d}},
+       Optab{AJGT, yjcond, Px, [23]uint8{0x7f, 0x8f}},
+       Optab{AJHI, yjcond, Px, [23]uint8{0x77, 0x87}},
+       Optab{AJLE, yjcond, Px, [23]uint8{0x7e, 0x8e}},
+       Optab{AJLS, yjcond, Px, [23]uint8{0x76, 0x86}},
+       Optab{AJLT, yjcond, Px, [23]uint8{0x7c, 0x8c}},
+       Optab{AJMI, yjcond, Px, [23]uint8{0x78, 0x88}},
+       Optab{AJMP, yjmp, Px, [23]uint8{0xff, 04, 0xeb, 0xe9}},
+       Optab{AJNE, yjcond, Px, [23]uint8{0x75, 0x85}},
+       Optab{AJOC, yjcond, Px, [23]uint8{0x71, 0x81, 00}},
+       Optab{AJOS, yjcond, Px, [23]uint8{0x70, 0x80, 00}},
+       Optab{AJPC, yjcond, Px, [23]uint8{0x7b, 0x8b}},
+       Optab{AJPL, yjcond, Px, [23]uint8{0x79, 0x89}},
+       Optab{AJPS, yjcond, Px, [23]uint8{0x7a, 0x8a}},
+       Optab{ALAHF, ynone, Px, [23]uint8{0x9f}},
+       Optab{ALARL, yml_rl, Pm, [23]uint8{0x02}},
+       Optab{ALARW, yml_rl, Pq, [23]uint8{0x02}},
+       Optab{ALDMXCSR, ysvrs, Pm, [23]uint8{0xae, 02, 0xae, 02}},
+       Optab{ALEAL, ym_rl, Px, [23]uint8{0x8d}},
+       Optab{ALEAQ, ym_rl, Pw, [23]uint8{0x8d}},
+       Optab{ALEAVEL, ynone, P32, [23]uint8{0xc9}},
+       Optab{ALEAVEQ, ynone, Py, [23]uint8{0xc9}},
+       Optab{ALEAVEW, ynone, Pe, [23]uint8{0xc9}},
+       Optab{ALEAW, ym_rl, Pe, [23]uint8{0x8d}},
+       Optab{ALOCK, ynone, Px, [23]uint8{0xf0}},
+       Optab{ALODSB, ynone, Pb, [23]uint8{0xac}},
+       Optab{ALODSL, ynone, Px, [23]uint8{0xad}},
+       Optab{ALODSQ, ynone, Pw, [23]uint8{0xad}},
+       Optab{ALODSW, ynone, Pe, [23]uint8{0xad}},
+       Optab{ALONG, ybyte, Px, [23]uint8{4}},
+       Optab{ALOOP, yloop, Px, [23]uint8{0xe2}},
+       Optab{ALOOPEQ, yloop, Px, [23]uint8{0xe1}},
+       Optab{ALOOPNE, yloop, Px, [23]uint8{0xe0}},
+       Optab{ALSLL, yml_rl, Pm, [23]uint8{0x03}},
+       Optab{ALSLW, yml_rl, Pq, [23]uint8{0x03}},
+       Optab{AMASKMOVOU, yxr, Pe, [23]uint8{0xf7}},
+       Optab{AMASKMOVQ, ymr, Pm, [23]uint8{0xf7}},
+       Optab{AMAXPD, yxm, Pe, [23]uint8{0x5f}},
+       Optab{AMAXPS, yxm, Pm, [23]uint8{0x5f}},
+       Optab{AMAXSD, yxm, Pf2, [23]uint8{0x5f}},
+       Optab{AMAXSS, yxm, Pf3, [23]uint8{0x5f}},
+       Optab{AMINPD, yxm, Pe, [23]uint8{0x5d}},
+       Optab{AMINPS, yxm, Pm, [23]uint8{0x5d}},
+       Optab{AMINSD, yxm, Pf2, [23]uint8{0x5d}},
+       Optab{AMINSS, yxm, Pf3, [23]uint8{0x5d}},
+       Optab{AMOVAPD, yxmov, Pe, [23]uint8{0x28, 0x29}},
+       Optab{AMOVAPS, yxmov, Pm, [23]uint8{0x28, 0x29}},
+       Optab{AMOVB, ymovb, Pb, [23]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
+       Optab{AMOVBLSX, ymb_rl, Pm, [23]uint8{0xbe}},
+       Optab{AMOVBLZX, ymb_rl, Pm, [23]uint8{0xb6}},
+       Optab{AMOVBQSX, ymb_rl, Pw, [23]uint8{0x0f, 0xbe}},
+       Optab{AMOVBQZX, ymb_rl, Pm, [23]uint8{0xb6}},
+       Optab{AMOVBWSX, ymb_rl, Pq, [23]uint8{0xbe}},
+       Optab{AMOVBWZX, ymb_rl, Pq, [23]uint8{0xb6}},
+       Optab{AMOVO, yxmov, Pe, [23]uint8{0x6f, 0x7f}},
+       Optab{AMOVOU, yxmov, Pf3, [23]uint8{0x6f, 0x7f}},
+       Optab{AMOVHLPS, yxr, Pm, [23]uint8{0x12}},
+       Optab{AMOVHPD, yxmov, Pe, [23]uint8{0x16, 0x17}},
+       Optab{AMOVHPS, yxmov, Pm, [23]uint8{0x16, 0x17}},
+       Optab{AMOVL, ymovl, Px, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
+       Optab{AMOVLHPS, yxr, Pm, [23]uint8{0x16}},
+       Optab{AMOVLPD, yxmov, Pe, [23]uint8{0x12, 0x13}},
+       Optab{AMOVLPS, yxmov, Pm, [23]uint8{0x12, 0x13}},
+       Optab{AMOVLQSX, yml_rl, Pw, [23]uint8{0x63}},
+       Optab{AMOVLQZX, yml_rl, Px, [23]uint8{0x8b}},
+       Optab{AMOVMSKPD, yxrrl, Pq, [23]uint8{0x50}},
+       Optab{AMOVMSKPS, yxrrl, Pm, [23]uint8{0x50}},
+       Optab{AMOVNTO, yxr_ml, Pe, [23]uint8{0xe7}},
+       Optab{AMOVNTPD, yxr_ml, Pe, [23]uint8{0x2b}},
+       Optab{AMOVNTPS, yxr_ml, Pm, [23]uint8{0x2b}},
+       Optab{AMOVNTQ, ymr_ml, Pm, [23]uint8{0xe7}},
+       Optab{AMOVQ, ymovq, Pw, [23]uint8{0x89, 0x8b, 0x31, 0xc7, 00, 0xb8, 0xc7, 00, 0x6f, 0x7f, 0x6e, 0x7e, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, Pe, 0x6e, Pe, 0x7e, 0}},
+       Optab{AMOVQOZX, ymrxr, Pf3, [23]uint8{0xd6, 0x7e}},
+       Optab{AMOVSB, ynone, Pb, [23]uint8{0xa4}},
+       Optab{AMOVSD, yxmov, Pf2, [23]uint8{0x10, 0x11}},
+       Optab{AMOVSL, ynone, Px, [23]uint8{0xa5}},
+       Optab{AMOVSQ, ynone, Pw, [23]uint8{0xa5}},
+       Optab{AMOVSS, yxmov, Pf3, [23]uint8{0x10, 0x11}},
+       Optab{AMOVSW, ynone, Pe, [23]uint8{0xa5}},
+       Optab{AMOVUPD, yxmov, Pe, [23]uint8{0x10, 0x11}},
+       Optab{AMOVUPS, yxmov, Pm, [23]uint8{0x10, 0x11}},
+       Optab{AMOVW, ymovw, Pe, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0}},
+       Optab{AMOVWLSX, yml_rl, Pm, [23]uint8{0xbf}},
+       Optab{AMOVWLZX, yml_rl, Pm, [23]uint8{0xb7}},
+       Optab{AMOVWQSX, yml_rl, Pw, [23]uint8{0x0f, 0xbf}},
+       Optab{AMOVWQZX, yml_rl, Pw, [23]uint8{0x0f, 0xb7}},
+       Optab{AMULB, ydivb, Pb, [23]uint8{0xf6, 04}},
+       Optab{AMULL, ydivl, Px, [23]uint8{0xf7, 04}},
+       Optab{AMULPD, yxm, Pe, [23]uint8{0x59}},
+       Optab{AMULPS, yxm, Ym, [23]uint8{0x59}},
+       Optab{AMULQ, ydivl, Pw, [23]uint8{0xf7, 04}},
+       Optab{AMULSD, yxm, Pf2, [23]uint8{0x59}},
+       Optab{AMULSS, yxm, Pf3, [23]uint8{0x59}},
+       Optab{AMULW, ydivl, Pe, [23]uint8{0xf7, 04}},
+       Optab{ANAME, nil, 0, [23]uint8{}},
+       Optab{ANEGB, yscond, Pb, [23]uint8{0xf6, 03}},
+       Optab{ANEGL, yscond, Px, [23]uint8{0xf7, 03}},
+       Optab{ANEGQ, yscond, Pw, [23]uint8{0xf7, 03}},
+       Optab{ANEGW, yscond, Pe, [23]uint8{0xf7, 03}},
+       Optab{ANOP, ynop, Px, [23]uint8{0, 0}},
+       Optab{ANOTB, yscond, Pb, [23]uint8{0xf6, 02}},
+       Optab{ANOTL, yscond, Px, [23]uint8{0xf7, 02}},
+       Optab{ANOTQ, yscond, Pw, [23]uint8{0xf7, 02}},
+       Optab{ANOTW, yscond, Pe, [23]uint8{0xf7, 02}},
+       Optab{AORB, yxorb, Pb, [23]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
+       Optab{AORL, yxorl, Px, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+       Optab{AORPD, yxm, Pq, [23]uint8{0x56}},
+       Optab{AORPS, yxm, Pm, [23]uint8{0x56}},
+       Optab{AORQ, yxorl, Pw, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+       Optab{AORW, yxorl, Pe, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+       Optab{AOUTB, yin, Pb, [23]uint8{0xe6, 0xee}},
+       Optab{AOUTL, yin, Px, [23]uint8{0xe7, 0xef}},
+       Optab{AOUTSB, ynone, Pb, [23]uint8{0x6e}},
+       Optab{AOUTSL, ynone, Px, [23]uint8{0x6f}},
+       Optab{AOUTSW, ynone, Pe, [23]uint8{0x6f}},
+       Optab{AOUTW, yin, Pe, [23]uint8{0xe7, 0xef}},
+       Optab{APACKSSLW, ymm, Py, [23]uint8{0x6b, Pe, 0x6b}},
+       Optab{APACKSSWB, ymm, Py, [23]uint8{0x63, Pe, 0x63}},
+       Optab{APACKUSWB, ymm, Py, [23]uint8{0x67, Pe, 0x67}},
+       Optab{APADDB, ymm, Py, [23]uint8{0xfc, Pe, 0xfc}},
+       Optab{APADDL, ymm, Py, [23]uint8{0xfe, Pe, 0xfe}},
+       Optab{APADDQ, yxm, Pe, [23]uint8{0xd4}},
+       Optab{APADDSB, ymm, Py, [23]uint8{0xec, Pe, 0xec}},
+       Optab{APADDSW, ymm, Py, [23]uint8{0xed, Pe, 0xed}},
+       Optab{APADDUSB, ymm, Py, [23]uint8{0xdc, Pe, 0xdc}},
+       Optab{APADDUSW, ymm, Py, [23]uint8{0xdd, Pe, 0xdd}},
+       Optab{APADDW, ymm, Py, [23]uint8{0xfd, Pe, 0xfd}},
+       Optab{APAND, ymm, Py, [23]uint8{0xdb, Pe, 0xdb}},
+       Optab{APANDN, ymm, Py, [23]uint8{0xdf, Pe, 0xdf}},
+       Optab{APAUSE, ynone, Px, [23]uint8{0xf3, 0x90}},
+       Optab{APAVGB, ymm, Py, [23]uint8{0xe0, Pe, 0xe0}},
+       Optab{APAVGW, ymm, Py, [23]uint8{0xe3, Pe, 0xe3}},
+       Optab{APCMPEQB, ymm, Py, [23]uint8{0x74, Pe, 0x74}},
+       Optab{APCMPEQL, ymm, Py, [23]uint8{0x76, Pe, 0x76}},
+       Optab{APCMPEQW, ymm, Py, [23]uint8{0x75, Pe, 0x75}},
+       Optab{APCMPGTB, ymm, Py, [23]uint8{0x64, Pe, 0x64}},
+       Optab{APCMPGTL, ymm, Py, [23]uint8{0x66, Pe, 0x66}},
+       Optab{APCMPGTW, ymm, Py, [23]uint8{0x65, Pe, 0x65}},
+       Optab{APEXTRW, yextrw, Pq, [23]uint8{0xc5, 00}},
+       Optab{APF2IL, ymfp, Px, [23]uint8{0x1d}},
+       Optab{APF2IW, ymfp, Px, [23]uint8{0x1c}},
+       Optab{API2FL, ymfp, Px, [23]uint8{0x0d}},
+       Optab{APFACC, ymfp, Px, [23]uint8{0xae}},
+       Optab{APFADD, ymfp, Px, [23]uint8{0x9e}},
+       Optab{APFCMPEQ, ymfp, Px, [23]uint8{0xb0}},
+       Optab{APFCMPGE, ymfp, Px, [23]uint8{0x90}},
+       Optab{APFCMPGT, ymfp, Px, [23]uint8{0xa0}},
+       Optab{APFMAX, ymfp, Px, [23]uint8{0xa4}},
+       Optab{APFMIN, ymfp, Px, [23]uint8{0x94}},
+       Optab{APFMUL, ymfp, Px, [23]uint8{0xb4}},
+       Optab{APFNACC, ymfp, Px, [23]uint8{0x8a}},
+       Optab{APFPNACC, ymfp, Px, [23]uint8{0x8e}},
+       Optab{APFRCP, ymfp, Px, [23]uint8{0x96}},
+       Optab{APFRCPIT1, ymfp, Px, [23]uint8{0xa6}},
+       Optab{APFRCPI2T, ymfp, Px, [23]uint8{0xb6}},
+       Optab{APFRSQIT1, ymfp, Px, [23]uint8{0xa7}},
+       Optab{APFRSQRT, ymfp, Px, [23]uint8{0x97}},
+       Optab{APFSUB, ymfp, Px, [23]uint8{0x9a}},
+       Optab{APFSUBR, ymfp, Px, [23]uint8{0xaa}},
+       Optab{APINSRW, yinsrw, Pq, [23]uint8{0xc4, 00}},
+       Optab{APINSRD, yinsr, Pq, [23]uint8{0x3a, 0x22, 00}},
+       Optab{APINSRQ, yinsr, Pq3, [23]uint8{0x3a, 0x22, 00}},
+       Optab{APMADDWL, ymm, Py, [23]uint8{0xf5, Pe, 0xf5}},
+       Optab{APMAXSW, yxm, Pe, [23]uint8{0xee}},
+       Optab{APMAXUB, yxm, Pe, [23]uint8{0xde}},
+       Optab{APMINSW, yxm, Pe, [23]uint8{0xea}},
+       Optab{APMINUB, yxm, Pe, [23]uint8{0xda}},
+       Optab{APMOVMSKB, ymskb, Px, [23]uint8{Pe, 0xd7, 0xd7}},
+       Optab{APMULHRW, ymfp, Px, [23]uint8{0xb7}},
+       Optab{APMULHUW, ymm, Py, [23]uint8{0xe4, Pe, 0xe4}},
+       Optab{APMULHW, ymm, Py, [23]uint8{0xe5, Pe, 0xe5}},
+       Optab{APMULLW, ymm, Py, [23]uint8{0xd5, Pe, 0xd5}},
+       Optab{APMULULQ, ymm, Py, [23]uint8{0xf4, Pe, 0xf4}},
+       Optab{APOPAL, ynone, P32, [23]uint8{0x61}},
+       Optab{APOPAW, ynone, Pe, [23]uint8{0x61}},
+       Optab{APOPFL, ynone, P32, [23]uint8{0x9d}},
+       Optab{APOPFQ, ynone, Py, [23]uint8{0x9d}},
+       Optab{APOPFW, ynone, Pe, [23]uint8{0x9d}},
+       Optab{APOPL, ypopl, P32, [23]uint8{0x58, 0x8f, 00}},
+       Optab{APOPQ, ypopl, Py, [23]uint8{0x58, 0x8f, 00}},
+       Optab{APOPW, ypopl, Pe, [23]uint8{0x58, 0x8f, 00}},
+       Optab{APOR, ymm, Py, [23]uint8{0xeb, Pe, 0xeb}},
+       Optab{APSADBW, yxm, Pq, [23]uint8{0xf6}},
+       Optab{APSHUFHW, yxshuf, Pf3, [23]uint8{0x70, 00}},
+       Optab{APSHUFL, yxshuf, Pq, [23]uint8{0x70, 00}},
+       Optab{APSHUFLW, yxshuf, Pf2, [23]uint8{0x70, 00}},
+       Optab{APSHUFW, ymshuf, Pm, [23]uint8{0x70, 00}},
+       Optab{APSHUFB, ymshufb, Pq, [23]uint8{0x38, 0x00}},
+       Optab{APSLLO, ypsdq, Pq, [23]uint8{0x73, 07}},
+       Optab{APSLLL, yps, Py, [23]uint8{0xf2, 0x72, 06, Pe, 0xf2, Pe, 0x72, 06}},
+       Optab{APSLLQ, yps, Py, [23]uint8{0xf3, 0x73, 06, Pe, 0xf3, Pe, 0x73, 06}},
+       Optab{APSLLW, yps, Py, [23]uint8{0xf1, 0x71, 06, Pe, 0xf1, Pe, 0x71, 06}},
+       Optab{APSRAL, yps, Py, [23]uint8{0xe2, 0x72, 04, Pe, 0xe2, Pe, 0x72, 04}},
+       Optab{APSRAW, yps, Py, [23]uint8{0xe1, 0x71, 04, Pe, 0xe1, Pe, 0x71, 04}},
+       Optab{APSRLO, ypsdq, Pq, [23]uint8{0x73, 03}},
+       Optab{APSRLL, yps, Py, [23]uint8{0xd2, 0x72, 02, Pe, 0xd2, Pe, 0x72, 02}},
+       Optab{APSRLQ, yps, Py, [23]uint8{0xd3, 0x73, 02, Pe, 0xd3, Pe, 0x73, 02}},
+       Optab{APSRLW, yps, Py, [23]uint8{0xd1, 0x71, 02, Pe, 0xe1, Pe, 0x71, 02}},
+       Optab{APSUBB, yxm, Pe, [23]uint8{0xf8}},
+       Optab{APSUBL, yxm, Pe, [23]uint8{0xfa}},
+       Optab{APSUBQ, yxm, Pe, [23]uint8{0xfb}},
+       Optab{APSUBSB, yxm, Pe, [23]uint8{0xe8}},
+       Optab{APSUBSW, yxm, Pe, [23]uint8{0xe9}},
+       Optab{APSUBUSB, yxm, Pe, [23]uint8{0xd8}},
+       Optab{APSUBUSW, yxm, Pe, [23]uint8{0xd9}},
+       Optab{APSUBW, yxm, Pe, [23]uint8{0xf9}},
+       Optab{APSWAPL, ymfp, Px, [23]uint8{0xbb}},
+       Optab{APUNPCKHBW, ymm, Py, [23]uint8{0x68, Pe, 0x68}},
+       Optab{APUNPCKHLQ, ymm, Py, [23]uint8{0x6a, Pe, 0x6a}},
+       Optab{APUNPCKHQDQ, yxm, Pe, [23]uint8{0x6d}},
+       Optab{APUNPCKHWL, ymm, Py, [23]uint8{0x69, Pe, 0x69}},
+       Optab{APUNPCKLBW, ymm, Py, [23]uint8{0x60, Pe, 0x60}},
+       Optab{APUNPCKLLQ, ymm, Py, [23]uint8{0x62, Pe, 0x62}},
+       Optab{APUNPCKLQDQ, yxm, Pe, [23]uint8{0x6c}},
+       Optab{APUNPCKLWL, ymm, Py, [23]uint8{0x61, Pe, 0x61}},
+       Optab{APUSHAL, ynone, P32, [23]uint8{0x60}},
+       Optab{APUSHAW, ynone, Pe, [23]uint8{0x60}},
+       Optab{APUSHFL, ynone, P32, [23]uint8{0x9c}},
+       Optab{APUSHFQ, ynone, Py, [23]uint8{0x9c}},
+       Optab{APUSHFW, ynone, Pe, [23]uint8{0x9c}},
+       Optab{APUSHL, ypushl, P32, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+       Optab{APUSHQ, ypushl, Py, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+       Optab{APUSHW, ypushl, Pe, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+       Optab{APXOR, ymm, Py, [23]uint8{0xef, Pe, 0xef}},
+       Optab{AQUAD, ybyte, Px, [23]uint8{8}},
+       Optab{ARCLB, yshb, Pb, [23]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
+       Optab{ARCLL, yshl, Px, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+       Optab{ARCLQ, yshl, Pw, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+       Optab{ARCLW, yshl, Pe, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+       Optab{ARCPPS, yxm, Pm, [23]uint8{0x53}},
+       Optab{ARCPSS, yxm, Pf3, [23]uint8{0x53}},
+       Optab{ARCRB, yshb, Pb, [23]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
+       Optab{ARCRL, yshl, Px, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+       Optab{ARCRQ, yshl, Pw, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+       Optab{ARCRW, yshl, Pe, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+       Optab{AREP, ynone, Px, [23]uint8{0xf3}},
+       Optab{AREPN, ynone, Px, [23]uint8{0xf2}},
+       Optab{ARET, ynone, Px, [23]uint8{0xc3}},
+       Optab{ARETFW, yret, Pe, [23]uint8{0xcb, 0xca}},
+       Optab{ARETFL, yret, Px, [23]uint8{0xcb, 0xca}},
+       Optab{ARETFQ, yret, Pw, [23]uint8{0xcb, 0xca}},
+       Optab{AROLB, yshb, Pb, [23]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
+       Optab{AROLL, yshl, Px, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+       Optab{AROLQ, yshl, Pw, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+       Optab{AROLW, yshl, Pe, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+       Optab{ARORB, yshb, Pb, [23]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
+       Optab{ARORL, yshl, Px, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+       Optab{ARORQ, yshl, Pw, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+       Optab{ARORW, yshl, Pe, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+       Optab{ARSQRTPS, yxm, Pm, [23]uint8{0x52}},
+       Optab{ARSQRTSS, yxm, Pf3, [23]uint8{0x52}},
+       Optab{ASAHF, ynone, Px, [23]uint8{0x86, 0xe0, 0x50, 0x9d}}, /* XCHGB AH,AL; PUSH AX; POPFL */
+       Optab{ASALB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+       Optab{ASALL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASALQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASALW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASARB, yshb, Pb, [23]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
+       Optab{ASARL, yshl, Px, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+       Optab{ASARQ, yshl, Pw, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+       Optab{ASARW, yshl, Pe, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+       Optab{ASBBB, yxorb, Pb, [23]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
+       Optab{ASBBL, yxorl, Px, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+       Optab{ASBBQ, yxorl, Pw, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+       Optab{ASBBW, yxorl, Pe, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+       Optab{ASCASB, ynone, Pb, [23]uint8{0xae}},
+       Optab{ASCASL, ynone, Px, [23]uint8{0xaf}},
+       Optab{ASCASQ, ynone, Pw, [23]uint8{0xaf}},
+       Optab{ASCASW, ynone, Pe, [23]uint8{0xaf}},
+       Optab{ASETCC, yscond, Pb, [23]uint8{0x0f, 0x93, 00}},
+       Optab{ASETCS, yscond, Pb, [23]uint8{0x0f, 0x92, 00}},
+       Optab{ASETEQ, yscond, Pb, [23]uint8{0x0f, 0x94, 00}},
+       Optab{ASETGE, yscond, Pb, [23]uint8{0x0f, 0x9d, 00}},
+       Optab{ASETGT, yscond, Pb, [23]uint8{0x0f, 0x9f, 00}},
+       Optab{ASETHI, yscond, Pb, [23]uint8{0x0f, 0x97, 00}},
+       Optab{ASETLE, yscond, Pb, [23]uint8{0x0f, 0x9e, 00}},
+       Optab{ASETLS, yscond, Pb, [23]uint8{0x0f, 0x96, 00}},
+       Optab{ASETLT, yscond, Pb, [23]uint8{0x0f, 0x9c, 00}},
+       Optab{ASETMI, yscond, Pb, [23]uint8{0x0f, 0x98, 00}},
+       Optab{ASETNE, yscond, Pb, [23]uint8{0x0f, 0x95, 00}},
+       Optab{ASETOC, yscond, Pb, [23]uint8{0x0f, 0x91, 00}},
+       Optab{ASETOS, yscond, Pb, [23]uint8{0x0f, 0x90, 00}},
+       Optab{ASETPC, yscond, Pb, [23]uint8{0x0f, 0x9b, 00}},
+       Optab{ASETPL, yscond, Pb, [23]uint8{0x0f, 0x99, 00}},
+       Optab{ASETPS, yscond, Pb, [23]uint8{0x0f, 0x9a, 00}},
+       Optab{ASHLB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+       Optab{ASHLL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASHLQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASHLW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+       Optab{ASHRB, yshb, Pb, [23]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
+       Optab{ASHRL, yshl, Px, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+       Optab{ASHRQ, yshl, Pw, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+       Optab{ASHRW, yshl, Pe, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+       Optab{ASHUFPD, yxshuf, Pq, [23]uint8{0xc6, 00}},
+       Optab{ASHUFPS, yxshuf, Pm, [23]uint8{0xc6, 00}},
+       Optab{ASQRTPD, yxm, Pe, [23]uint8{0x51}},
+       Optab{ASQRTPS, yxm, Pm, [23]uint8{0x51}},
+       Optab{ASQRTSD, yxm, Pf2, [23]uint8{0x51}},
+       Optab{ASQRTSS, yxm, Pf3, [23]uint8{0x51}},
+       Optab{ASTC, ynone, Px, [23]uint8{0xf9}},
+       Optab{ASTD, ynone, Px, [23]uint8{0xfd}},
+       Optab{ASTI, ynone, Px, [23]uint8{0xfb}},
+       Optab{ASTMXCSR, ysvrs, Pm, [23]uint8{0xae, 03, 0xae, 03}},
+       Optab{ASTOSB, ynone, Pb, [23]uint8{0xaa}},
+       Optab{ASTOSL, ynone, Px, [23]uint8{0xab}},
+       Optab{ASTOSQ, ynone, Pw, [23]uint8{0xab}},
+       Optab{ASTOSW, ynone, Pe, [23]uint8{0xab}},
+       Optab{ASUBB, yxorb, Pb, [23]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
+       Optab{ASUBL, yaddl, Px, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+       Optab{ASUBPD, yxm, Pe, [23]uint8{0x5c}},
+       Optab{ASUBPS, yxm, Pm, [23]uint8{0x5c}},
+       Optab{ASUBQ, yaddl, Pw, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+       Optab{ASUBSD, yxm, Pf2, [23]uint8{0x5c}},
+       Optab{ASUBSS, yxm, Pf3, [23]uint8{0x5c}},
+       Optab{ASUBW, yaddl, Pe, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+       Optab{ASWAPGS, ynone, Pm, [23]uint8{0x01, 0xf8}},
+       Optab{ASYSCALL, ynone, Px, [23]uint8{0x0f, 0x05}}, /* fast syscall */
+       Optab{ATESTB, ytestb, Pb, [23]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
+       Optab{ATESTL, ytestl, Px, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+       Optab{ATESTQ, ytestl, Pw, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+       Optab{ATESTW, ytestl, Pe, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+       Optab{ATEXT, ytext, Px, [23]uint8{}},
+       Optab{AUCOMISD, yxcmp, Pe, [23]uint8{0x2e}},
+       Optab{AUCOMISS, yxcmp, Pm, [23]uint8{0x2e}},
+       Optab{AUNPCKHPD, yxm, Pe, [23]uint8{0x15}},
+       Optab{AUNPCKHPS, yxm, Pm, [23]uint8{0x15}},
+       Optab{AUNPCKLPD, yxm, Pe, [23]uint8{0x14}},
+       Optab{AUNPCKLPS, yxm, Pm, [23]uint8{0x14}},
+       Optab{AVERR, ydivl, Pm, [23]uint8{0x00, 04}},
+       Optab{AVERW, ydivl, Pm, [23]uint8{0x00, 05}},
+       Optab{AWAIT, ynone, Px, [23]uint8{0x9b}},
+       Optab{AWORD, ybyte, Px, [23]uint8{2}},
+       Optab{AXCHGB, yml_mb, Pb, [23]uint8{0x86, 0x86}},
+       Optab{AXCHGL, yxchg, Px, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+       Optab{AXCHGQ, yxchg, Pw, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+       Optab{AXCHGW, yxchg, Pe, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+       Optab{AXLAT, ynone, Px, [23]uint8{0xd7}},
+       Optab{AXORB, yxorb, Pb, [23]uint8{0x34, 0x80, 06, 0x30, 0x32}},
+       Optab{AXORL, yxorl, Px, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+       Optab{AXORPD, yxm, Pe, [23]uint8{0x57}},
+       Optab{AXORPS, yxm, Pm, [23]uint8{0x57}},
+       Optab{AXORQ, yxorl, Pw, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+       Optab{AXORW, yxorl, Pe, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+       Optab{AFMOVB, yfmvx, Px, [23]uint8{0xdf, 04}},
+       Optab{AFMOVBP, yfmvp, Px, [23]uint8{0xdf, 06}},
+       Optab{AFMOVD, yfmvd, Px, [23]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
+       Optab{AFMOVDP, yfmvdp, Px, [23]uint8{0xdd, 03, 0xdd, 03}},
+       Optab{AFMOVF, yfmvf, Px, [23]uint8{0xd9, 00, 0xd9, 02}},
+       Optab{AFMOVFP, yfmvp, Px, [23]uint8{0xd9, 03}},
+       Optab{AFMOVL, yfmvf, Px, [23]uint8{0xdb, 00, 0xdb, 02}},
+       Optab{AFMOVLP, yfmvp, Px, [23]uint8{0xdb, 03}},
+       Optab{AFMOVV, yfmvx, Px, [23]uint8{0xdf, 05}},
+       Optab{AFMOVVP, yfmvp, Px, [23]uint8{0xdf, 07}},
+       Optab{AFMOVW, yfmvf, Px, [23]uint8{0xdf, 00, 0xdf, 02}},
+       Optab{AFMOVWP, yfmvp, Px, [23]uint8{0xdf, 03}},
+       Optab{AFMOVX, yfmvx, Px, [23]uint8{0xdb, 05}},
+       Optab{AFMOVXP, yfmvp, Px, [23]uint8{0xdb, 07}},
+       Optab{AFCOMB, nil, 0, [23]uint8{}},
+       Optab{AFCOMBP, nil, 0, [23]uint8{}},
+       Optab{AFCOMD, yfadd, Px, [23]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}},  /* botch */
+       Optab{AFCOMDP, yfadd, Px, [23]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
+       Optab{AFCOMDPP, ycompp, Px, [23]uint8{0xde, 03}},
+       Optab{AFCOMF, yfmvx, Px, [23]uint8{0xd8, 02}},
+       Optab{AFCOMFP, yfmvx, Px, [23]uint8{0xd8, 03}},
+       Optab{AFCOML, yfmvx, Px, [23]uint8{0xda, 02}},
+       Optab{AFCOMLP, yfmvx, Px, [23]uint8{0xda, 03}},
+       Optab{AFCOMW, yfmvx, Px, [23]uint8{0xde, 02}},
+       Optab{AFCOMWP, yfmvx, Px, [23]uint8{0xde, 03}},
+       Optab{AFUCOM, ycompp, Px, [23]uint8{0xdd, 04}},
+       Optab{AFUCOMP, ycompp, Px, [23]uint8{0xdd, 05}},
+       Optab{AFUCOMPP, ycompp, Px, [23]uint8{0xda, 13}},
+       Optab{AFADDDP, yfaddp, Px, [23]uint8{0xde, 00}},
+       Optab{AFADDW, yfmvx, Px, [23]uint8{0xde, 00}},
+       Optab{AFADDL, yfmvx, Px, [23]uint8{0xda, 00}},
+       Optab{AFADDF, yfmvx, Px, [23]uint8{0xd8, 00}},
+       Optab{AFADDD, yfadd, Px, [23]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
+       Optab{AFMULDP, yfaddp, Px, [23]uint8{0xde, 01}},
+       Optab{AFMULW, yfmvx, Px, [23]uint8{0xde, 01}},
+       Optab{AFMULL, yfmvx, Px, [23]uint8{0xda, 01}},
+       Optab{AFMULF, yfmvx, Px, [23]uint8{0xd8, 01}},
+       Optab{AFMULD, yfadd, Px, [23]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
+       Optab{AFSUBDP, yfaddp, Px, [23]uint8{0xde, 05}},
+       Optab{AFSUBW, yfmvx, Px, [23]uint8{0xde, 04}},
+       Optab{AFSUBL, yfmvx, Px, [23]uint8{0xda, 04}},
+       Optab{AFSUBF, yfmvx, Px, [23]uint8{0xd8, 04}},
+       Optab{AFSUBD, yfadd, Px, [23]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
+       Optab{AFSUBRDP, yfaddp, Px, [23]uint8{0xde, 04}},
+       Optab{AFSUBRW, yfmvx, Px, [23]uint8{0xde, 05}},
+       Optab{AFSUBRL, yfmvx, Px, [23]uint8{0xda, 05}},
+       Optab{AFSUBRF, yfmvx, Px, [23]uint8{0xd8, 05}},
+       Optab{AFSUBRD, yfadd, Px, [23]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
+       Optab{AFDIVDP, yfaddp, Px, [23]uint8{0xde, 07}},
+       Optab{AFDIVW, yfmvx, Px, [23]uint8{0xde, 06}},
+       Optab{AFDIVL, yfmvx, Px, [23]uint8{0xda, 06}},
+       Optab{AFDIVF, yfmvx, Px, [23]uint8{0xd8, 06}},
+       Optab{AFDIVD, yfadd, Px, [23]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
+       Optab{AFDIVRDP, yfaddp, Px, [23]uint8{0xde, 06}},
+       Optab{AFDIVRW, yfmvx, Px, [23]uint8{0xde, 07}},
+       Optab{AFDIVRL, yfmvx, Px, [23]uint8{0xda, 07}},
+       Optab{AFDIVRF, yfmvx, Px, [23]uint8{0xd8, 07}},
+       Optab{AFDIVRD, yfadd, Px, [23]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
+       Optab{AFXCHD, yfxch, Px, [23]uint8{0xd9, 01, 0xd9, 01}},
+       Optab{AFFREE, nil, 0, [23]uint8{}},
+       Optab{AFLDCW, ystcw, Px, [23]uint8{0xd9, 05, 0xd9, 05}},
+       Optab{AFLDENV, ystcw, Px, [23]uint8{0xd9, 04, 0xd9, 04}},
+       Optab{AFRSTOR, ysvrs, Px, [23]uint8{0xdd, 04, 0xdd, 04}},
+       Optab{AFSAVE, ysvrs, Px, [23]uint8{0xdd, 06, 0xdd, 06}},
+       Optab{AFSTCW, ystcw, Px, [23]uint8{0xd9, 07, 0xd9, 07}},
+       Optab{AFSTENV, ystcw, Px, [23]uint8{0xd9, 06, 0xd9, 06}},
+       Optab{AFSTSW, ystsw, Px, [23]uint8{0xdd, 07, 0xdf, 0xe0}},
+       Optab{AF2XM1, ynone, Px, [23]uint8{0xd9, 0xf0}},
+       Optab{AFABS, ynone, Px, [23]uint8{0xd9, 0xe1}},
+       Optab{AFCHS, ynone, Px, [23]uint8{0xd9, 0xe0}},
+       Optab{AFCLEX, ynone, Px, [23]uint8{0xdb, 0xe2}},
+       Optab{AFCOS, ynone, Px, [23]uint8{0xd9, 0xff}},
+       Optab{AFDECSTP, ynone, Px, [23]uint8{0xd9, 0xf6}},
+       Optab{AFINCSTP, ynone, Px, [23]uint8{0xd9, 0xf7}},
+       Optab{AFINIT, ynone, Px, [23]uint8{0xdb, 0xe3}},
+       Optab{AFLD1, ynone, Px, [23]uint8{0xd9, 0xe8}},
+       Optab{AFLDL2E, ynone, Px, [23]uint8{0xd9, 0xea}},
+       Optab{AFLDL2T, ynone, Px, [23]uint8{0xd9, 0xe9}},
+       Optab{AFLDLG2, ynone, Px, [23]uint8{0xd9, 0xec}},
+       Optab{AFLDLN2, ynone, Px, [23]uint8{0xd9, 0xed}},
+       Optab{AFLDPI, ynone, Px, [23]uint8{0xd9, 0xeb}},
+       Optab{AFLDZ, ynone, Px, [23]uint8{0xd9, 0xee}},
+       Optab{AFNOP, ynone, Px, [23]uint8{0xd9, 0xd0}},
+       Optab{AFPATAN, ynone, Px, [23]uint8{0xd9, 0xf3}},
+       Optab{AFPREM, ynone, Px, [23]uint8{0xd9, 0xf8}},
+       Optab{AFPREM1, ynone, Px, [23]uint8{0xd9, 0xf5}},
+       Optab{AFPTAN, ynone, Px, [23]uint8{0xd9, 0xf2}},
+       Optab{AFRNDINT, ynone, Px, [23]uint8{0xd9, 0xfc}},
+       Optab{AFSCALE, ynone, Px, [23]uint8{0xd9, 0xfd}},
+       Optab{AFSIN, ynone, Px, [23]uint8{0xd9, 0xfe}},
+       Optab{AFSINCOS, ynone, Px, [23]uint8{0xd9, 0xfb}},
+       Optab{AFSQRT, ynone, Px, [23]uint8{0xd9, 0xfa}},
+       Optab{AFTST, ynone, Px, [23]uint8{0xd9, 0xe4}},
+       Optab{AFXAM, ynone, Px, [23]uint8{0xd9, 0xe5}},
+       Optab{AFXTRACT, ynone, Px, [23]uint8{0xd9, 0xf4}},
+       Optab{AFYL2X, ynone, Px, [23]uint8{0xd9, 0xf1}},
+       Optab{AFYL2XP1, ynone, Px, [23]uint8{0xd9, 0xf9}},
+       Optab{ACMPXCHGB, yrb_mb, Pb, [23]uint8{0x0f, 0xb0}},
+       Optab{ACMPXCHGL, yrl_ml, Px, [23]uint8{0x0f, 0xb1}},
+       Optab{ACMPXCHGW, yrl_ml, Pe, [23]uint8{0x0f, 0xb1}},
+       Optab{ACMPXCHGQ, yrl_ml, Pw, [23]uint8{0x0f, 0xb1}},
+       Optab{ACMPXCHG8B, yscond, Pm, [23]uint8{0xc7, 01}},
+       Optab{AINVD, ynone, Pm, [23]uint8{0x08}},
+       Optab{AINVLPG, ymbs, Pm, [23]uint8{0x01, 07}},
+       Optab{ALFENCE, ynone, Pm, [23]uint8{0xae, 0xe8}},
+       Optab{AMFENCE, ynone, Pm, [23]uint8{0xae, 0xf0}},
+       Optab{AMOVNTIL, yrl_ml, Pm, [23]uint8{0xc3}},
+       Optab{AMOVNTIQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc3}},
+       Optab{ARDMSR, ynone, Pm, [23]uint8{0x32}},
+       Optab{ARDPMC, ynone, Pm, [23]uint8{0x33}},
+       Optab{ARDTSC, ynone, Pm, [23]uint8{0x31}},
+       Optab{ARSM, ynone, Pm, [23]uint8{0xaa}},
+       Optab{ASFENCE, ynone, Pm, [23]uint8{0xae, 0xf8}},
+       Optab{ASYSRET, ynone, Pm, [23]uint8{0x07}},
+       Optab{AWBINVD, ynone, Pm, [23]uint8{0x09}},
+       Optab{AWRMSR, ynone, Pm, [23]uint8{0x30}},
+       Optab{AXADDB, yrb_mb, Pb, [23]uint8{0x0f, 0xc0}},
+       Optab{AXADDL, yrl_ml, Px, [23]uint8{0x0f, 0xc1}},
+       Optab{AXADDQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc1}},
+       Optab{AXADDW, yrl_ml, Pe, [23]uint8{0x0f, 0xc1}},
+       Optab{ACRC32B, ycrc32l, Px, [23]uint8{0xf2, 0x0f, 0x38, 0xf0, 0}},
+       Optab{ACRC32Q, ycrc32l, Pw, [23]uint8{0xf2, 0x0f, 0x38, 0xf1, 0}},
+       Optab{APREFETCHT0, yprefetch, Pm, [23]uint8{0x18, 01}},
+       Optab{APREFETCHT1, yprefetch, Pm, [23]uint8{0x18, 02}},
+       Optab{APREFETCHT2, yprefetch, Pm, [23]uint8{0x18, 03}},
+       Optab{APREFETCHNTA, yprefetch, Pm, [23]uint8{0x18, 00}},
+       Optab{AMOVQL, yrl_ml, Px, [23]uint8{0x89}},
+       Optab{AUNDEF, ynone, Px, [23]uint8{0x0f, 0x0b}},
+       Optab{AAESENC, yaes, Pq, [23]uint8{0x38, 0xdc, 0}},
+       Optab{AAESENCLAST, yaes, Pq, [23]uint8{0x38, 0xdd, 0}},
+       Optab{AAESDEC, yaes, Pq, [23]uint8{0x38, 0xde, 0}},
+       Optab{AAESDECLAST, yaes, Pq, [23]uint8{0x38, 0xdf, 0}},
+       Optab{AAESIMC, yaes, Pq, [23]uint8{0x38, 0xdb, 0}},
+       Optab{AAESKEYGENASSIST, yaes2, Pq, [23]uint8{0x3a, 0xdf, 0}},
+       Optab{APSHUFD, yaes2, Pq, [23]uint8{0x70, 0}},
+       Optab{APCLMULQDQ, yxshuf, Pq, [23]uint8{0x3a, 0x44, 0}},
+       Optab{AUSEFIELD, ynop, Px, [23]uint8{0, 0}},
+       Optab{ATYPE, nil, 0, [23]uint8{}},
+       Optab{AFUNCDATA, yfuncdata, Px, [23]uint8{0, 0}},
+       Optab{APCDATA, ypcdata, Px, [23]uint8{0, 0}},
+       Optab{ACHECKNIL, nil, 0, [23]uint8{}},
+       Optab{AVARDEF, nil, 0, [23]uint8{}},
+       Optab{AVARKILL, nil, 0, [23]uint8{}},
+       Optab{ADUFFCOPY, yduff, Px, [23]uint8{0xe8}},
+       Optab{ADUFFZERO, yduff, Px, [23]uint8{0xe8}},
+       Optab{AEND, nil, 0, [23]uint8{}},
+       Optab{0, nil, 0, [23]uint8{}},
+}
+
+var opindex [ALAST + 1]*Optab
+
+// isextern reports whether s describes an external symbol that must avoid pc-relative addressing.
+// This happens on systems like Solaris that call .so functions instead of system calls.
+// It does not seem to be necessary for any other systems. This is probably working
+// around a Solaris-specific bug that should be fixed differently, but we don't know
+// what that bug is. And this does fix it.
+func isextern(s *obj.LSym) int {
+
+       // All the Solaris dynamic imports from libc.so begin with "libc_".
+       return bool2int(strings.HasPrefix(s.Name, "libc_"))
+}
+
+// single-instruction no-ops of various lengths.
+// constructed by hand and disassembled with gdb to verify.
+// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
+var nop = [][16]uint8{
+       [16]uint8{0x90},
+       [16]uint8{0x66, 0x90},
+       [16]uint8{0x0F, 0x1F, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x40, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
+       [16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+       [16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+       [16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+}
+
+// Native Client rejects the repeated 0x66 prefix.
+// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+func fillnop(p []byte, n int) {
+
+       var m int
+
+       for n > 0 {
+               m = n
+               if m > len(nop) {
+                       m = len(nop)
+               }
+               copy(p[:m], nop[m-1][:m])
+               p = p[m:]
+               n -= m
+       }
+}
+
+func naclpad(ctxt *obj.Link, s *obj.LSym, c int32, pad int32) int32 {
+       obj.Symgrow(ctxt, s, int64(c)+int64(pad))
+       fillnop(s.P[c:], int(pad))
+       return c + pad
+}
+
+func spadjop(ctxt *obj.Link, p *obj.Prog, l int, q int) int {
+       if p.Mode != 64 || ctxt.Arch.Ptrsize == 4 {
+               return l
+       }
+       return q
+}
+
+func span6(ctxt *obj.Link, s *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var c int32
+       var v int32
+       var loop int32
+       var bp []byte
+       var n int
+       var m int
+       var i int
+
+       ctxt.Cursym = s
+
+       if s.P != nil {
+               return
+       }
+
+       if ycover[0] == 0 {
+               instinit()
+       }
+
+       for p = ctxt.Cursym.Text; p != nil; p = p.Link {
+               n = 0
+               if p.To.Type == D_BRANCH {
+                       if p.Pcond == nil {
+                               p.Pcond = p
+                       }
+               }
+               q = p.Pcond
+               if q != nil {
+                       if q.Back != 2 {
+                               n = 1
+                       }
+               }
+               p.Back = uint8(n)
+               if p.As == AADJSP {
+                       p.To.Type = D_SP
+                       v = int32(-p.From.Offset)
+                       p.From.Offset = int64(v)
+                       p.As = int16(spadjop(ctxt, p, AADDL, AADDQ))
+                       if v < 0 {
+                               p.As = int16(spadjop(ctxt, p, ASUBL, ASUBQ))
+                               v = -v
+                               p.From.Offset = int64(v)
+                       }
+
+                       if v == 0 {
+                               p.As = ANOP
+                       }
+               }
+       }
+
+       for p = s.Text; p != nil; p = p.Link {
+               p.Back = 2 // use short branches first time through
+               q = p.Pcond
+               if q != nil && (q.Back&2 != 0) {
+                       p.Back |= 1 // backward jump
+                       q.Back |= 4 // loop head
+               }
+
+               if p.As == AADJSP {
+                       p.To.Type = D_SP
+                       v = int32(-p.From.Offset)
+                       p.From.Offset = int64(v)
+                       p.As = int16(spadjop(ctxt, p, AADDL, AADDQ))
+                       if v < 0 {
+                               p.As = int16(spadjop(ctxt, p, ASUBL, ASUBQ))
+                               v = -v
+                               p.From.Offset = int64(v)
+                       }
+
+                       if v == 0 {
+                               p.As = ANOP
+                       }
+               }
+       }
+
+       n = 0
+       for {
+               loop = 0
+               for i = 0; i < len(s.R); i++ {
+                       s.R[i] = obj.Reloc{}
+               }
+               s.R = s.R[:0]
+               s.P = s.P[:0]
+               c = 0
+               for p = s.Text; p != nil; p = p.Link {
+                       if ctxt.Headtype == obj.Hnacl && p.Isize > 0 {
+                               var deferreturn *obj.LSym
+
+                               if deferreturn == nil {
+                                       deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+                               }
+
+                               // pad everything to avoid crossing 32-byte boundary
+                               if c>>5 != (c+int32(p.Isize)-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // pad call deferreturn to start at 32-byte boundary
+                               // so that subtracting 5 in jmpdefer will jump back
+                               // to that boundary and rerun the call.
+                               if p.As == ACALL && p.To.Sym == deferreturn {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // pad call to end at 32-byte boundary
+                               if p.As == ACALL {
+
+                                       c = naclpad(ctxt, s, c, -(c+int32(p.Isize))&31)
+                               }
+
+                               // the linker treats REP and STOSQ as different instructions
+                               // but in fact the REP is a prefix on the STOSQ.
+                               // make sure REP has room for 2 more bytes, so that
+                               // padding will not be inserted before the next instruction.
+                               if (p.As == AREP || p.As == AREPN) && c>>5 != (c+3-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+
+                               // same for LOCK.
+                               // various instructions follow; the longest is 4 bytes.
+                               // give ourselves 8 bytes so as to avoid surprises.
+                               if p.As == ALOCK && c>>5 != (c+8-1)>>5 {
+
+                                       c = naclpad(ctxt, s, c, -c&31)
+                               }
+                       }
+
+                       if (p.Back&4 != 0) && c&(LoopAlign-1) != 0 {
+                               // pad with NOPs
+                               v = -c & (LoopAlign - 1)
+
+                               if v <= MaxLoopPad {
+                                       obj.Symgrow(ctxt, s, int64(c)+int64(v))
+                                       fillnop(s.P[c:], int(v))
+                                       c += v
+                               }
+                       }
+
+                       p.Pc = int64(c)
+
+                       // process forward jumps to p
+                       for q = p.Comefrom; q != nil; q = q.Forwd {
+
+                               v = int32(p.Pc - (q.Pc + int64(q.Mark)))
+                               if q.Back&2 != 0 { // short
+                                       if v > 127 {
+                                               loop++
+                                               q.Back ^= 2
+                                       }
+
+                                       if q.As == AJCXZL {
+                                               s.P[q.Pc+2] = byte(v)
+                                       } else {
+
+                                               s.P[q.Pc+1] = byte(v)
+                                       }
+                               } else {
+
+                                       bp = s.P[q.Pc+int64(q.Mark)-4:]
+                                       bp[0] = byte(v)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 8)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 16)
+                                       bp = bp[1:]
+                                       bp[0] = byte(v >> 24)
+                               }
+                       }
+
+                       p.Comefrom = nil
+
+                       p.Pc = int64(c)
+                       asmins(ctxt, p)
+                       m = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+                       if int(p.Isize) != m {
+                               p.Isize = uint8(m)
+                               loop++
+                       }
+
+                       obj.Symgrow(ctxt, s, p.Pc+int64(m))
+                       copy(s.P[p.Pc:][:m], ctxt.And[:m])
+                       p.Mark = uint16(m)
+                       c += int32(m)
+               }
+
+               n++
+               if n > 20 {
+                       ctxt.Diag("span must be looping")
+                       log.Fatalf("loop")
+               }
+               if !(loop != 0) {
+                       break
+               }
+       }
+
+       if ctxt.Headtype == obj.Hnacl {
+               c = naclpad(ctxt, s, c, -c&31)
+       }
+
+       c += -c & (FuncAlign - 1)
+       s.Size = int64(c)
+
+       if false { /* debug['a'] > 1 */
+               fmt.Printf("span1 %s %d (%d tries)\n %.6x", s.Name, s.Size, n, 0)
+               for i = 0; i < len(s.P); i++ {
+                       fmt.Printf(" %.2x", s.P[i])
+                       if i%16 == 15 {
+                               fmt.Printf("\n  %.6x", uint(i+1))
+                       }
+               }
+
+               if i%16 != 0 {
+                       fmt.Printf("\n")
+               }
+
+               for i = 0; i < len(s.R); i++ {
+                       var r *obj.Reloc
+
+                       r = &s.R[i]
+                       fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add)
+               }
+       }
+}
+
+func instinit() {
+       var c int
+       var i int
+
+       for i = 1; optab[i].as != 0; i++ {
+               c = int(optab[i].as)
+               if opindex[c] != nil {
+                       log.Fatalf("phase error in optab: %d (%v)", i, Aconv(c))
+               }
+               opindex[c] = &optab[i]
+       }
+
+       for i = 0; i < Ymax; i++ {
+               ycover[i*Ymax+i] = 1
+       }
+
+       ycover[Yi0*Ymax+Yi8] = 1
+       ycover[Yi1*Ymax+Yi8] = 1
+
+       ycover[Yi0*Ymax+Ys32] = 1
+       ycover[Yi1*Ymax+Ys32] = 1
+       ycover[Yi8*Ymax+Ys32] = 1
+
+       ycover[Yi0*Ymax+Yi32] = 1
+       ycover[Yi1*Ymax+Yi32] = 1
+       ycover[Yi8*Ymax+Yi32] = 1
+       ycover[Ys32*Ymax+Yi32] = 1
+
+       ycover[Yi0*Ymax+Yi64] = 1
+       ycover[Yi1*Ymax+Yi64] = 1
+       ycover[Yi8*Ymax+Yi64] = 1
+       ycover[Ys32*Ymax+Yi64] = 1
+       ycover[Yi32*Ymax+Yi64] = 1
+
+       ycover[Yal*Ymax+Yrb] = 1
+       ycover[Ycl*Ymax+Yrb] = 1
+       ycover[Yax*Ymax+Yrb] = 1
+       ycover[Ycx*Ymax+Yrb] = 1
+       ycover[Yrx*Ymax+Yrb] = 1
+       ycover[Yrl*Ymax+Yrb] = 1
+
+       ycover[Ycl*Ymax+Ycx] = 1
+
+       ycover[Yax*Ymax+Yrx] = 1
+       ycover[Ycx*Ymax+Yrx] = 1
+
+       ycover[Yax*Ymax+Yrl] = 1
+       ycover[Ycx*Ymax+Yrl] = 1
+       ycover[Yrx*Ymax+Yrl] = 1
+
+       ycover[Yf0*Ymax+Yrf] = 1
+
+       ycover[Yal*Ymax+Ymb] = 1
+       ycover[Ycl*Ymax+Ymb] = 1
+       ycover[Yax*Ymax+Ymb] = 1
+       ycover[Ycx*Ymax+Ymb] = 1
+       ycover[Yrx*Ymax+Ymb] = 1
+       ycover[Yrb*Ymax+Ymb] = 1
+       ycover[Yrl*Ymax+Ymb] = 1
+       ycover[Ym*Ymax+Ymb] = 1
+
+       ycover[Yax*Ymax+Yml] = 1
+       ycover[Ycx*Ymax+Yml] = 1
+       ycover[Yrx*Ymax+Yml] = 1
+       ycover[Yrl*Ymax+Yml] = 1
+       ycover[Ym*Ymax+Yml] = 1
+
+       ycover[Yax*Ymax+Ymm] = 1
+       ycover[Ycx*Ymax+Ymm] = 1
+       ycover[Yrx*Ymax+Ymm] = 1
+       ycover[Yrl*Ymax+Ymm] = 1
+       ycover[Ym*Ymax+Ymm] = 1
+       ycover[Ymr*Ymax+Ymm] = 1
+
+       ycover[Ym*Ymax+Yxm] = 1
+       ycover[Yxr*Ymax+Yxm] = 1
+
+       for i = 0; i < D_NONE; i++ {
+               reg[i] = -1
+               if i >= D_AL && i <= D_R15B {
+                       reg[i] = (i - D_AL) & 7
+                       if i >= D_SPB && i <= D_DIB {
+                               regrex[i] = 0x40
+                       }
+                       if i >= D_R8B && i <= D_R15B {
+                               regrex[i] = Rxr | Rxx | Rxb
+                       }
+               }
+
+               if i >= D_AH && i <= D_BH {
+                       reg[i] = 4 + ((i - D_AH) & 7)
+               }
+               if i >= D_AX && i <= D_R15 {
+                       reg[i] = (i - D_AX) & 7
+                       if i >= D_R8 {
+                               regrex[i] = Rxr | Rxx | Rxb
+                       }
+               }
+
+               if i >= D_F0 && i <= D_F0+7 {
+                       reg[i] = (i - D_F0) & 7
+               }
+               if i >= D_M0 && i <= D_M0+7 {
+                       reg[i] = (i - D_M0) & 7
+               }
+               if i >= D_X0 && i <= D_X0+15 {
+                       reg[i] = (i - D_X0) & 7
+                       if i >= D_X0+8 {
+                               regrex[i] = Rxr | Rxx | Rxb
+                       }
+               }
+
+               if i >= D_CR+8 && i <= D_CR+15 {
+                       regrex[i] = Rxr
+               }
+       }
+}
+
+func prefixof(ctxt *obj.Link, a *obj.Addr) int {
+       switch a.Type {
+       case D_INDIR + D_CS:
+               return 0x2e
+
+       case D_INDIR + D_DS:
+               return 0x3e
+
+       case D_INDIR + D_ES:
+               return 0x26
+
+       case D_INDIR + D_FS:
+               return 0x64
+
+       case D_INDIR + D_GS:
+               return 0x65
+
+               // NOTE: Systems listed here should be only systems that
+       // support direct TLS references like 8(TLS) implemented as
+       // direct references from FS or GS. Systems that require
+       // the initial-exec model, where you load the TLS base into
+       // a register and then index from that register, do not reach
+       // this code and should not be listed.
+       case D_INDIR + D_TLS:
+               switch ctxt.Headtype {
+
+               default:
+                       log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
+
+               case obj.Hdragonfly,
+                       obj.Hfreebsd,
+                       obj.Hlinux,
+                       obj.Hnetbsd,
+                       obj.Hopenbsd,
+                       obj.Hsolaris:
+                       return 0x64 // FS
+
+               case obj.Hdarwin:
+                       return 0x65 // GS
+               }
+       }
+
+       switch a.Index {
+       case D_CS:
+               return 0x2e
+
+       case D_DS:
+               return 0x3e
+
+       case D_ES:
+               return 0x26
+
+       case D_FS:
+               return 0x64
+
+       case D_GS:
+               return 0x65
+       }
+
+       return 0
+}
+
+func oclass(ctxt *obj.Link, a *obj.Addr) int {
+       var v int64
+       var l int32
+
+       if a.Type >= D_INDIR || a.Index != D_NONE {
+               if a.Index != D_NONE && a.Scale == 0 {
+                       if a.Type == D_ADDR {
+                               switch a.Index {
+                               case D_EXTERN,
+                                       D_STATIC:
+                                       if a.Sym != nil && isextern(a.Sym) != 0 {
+                                               return Yi32
+                                       }
+                                       return Yiauto // use pc-relative addressing
+
+                               case D_AUTO,
+                                       D_PARAM:
+                                       return Yiauto
+                               }
+
+                               return Yxxx
+                       }
+
+                       return Ycol
+               }
+
+               return Ym
+       }
+
+       switch a.Type {
+       case D_AL:
+               return Yal
+
+       case D_AX:
+               return Yax
+
+               /*
+                       case D_SPB:
+               */
+       case D_BPB,
+               D_SIB,
+               D_DIB,
+               D_R8B,
+               D_R9B,
+               D_R10B,
+               D_R11B,
+               D_R12B,
+               D_R13B,
+               D_R14B,
+               D_R15B:
+               if ctxt.Asmode != 64 {
+
+                       return Yxxx
+               }
+               fallthrough
+
+       case D_DL,
+               D_BL,
+               D_AH,
+               D_CH,
+               D_DH,
+               D_BH:
+               return Yrb
+
+       case D_CL:
+               return Ycl
+
+       case D_CX:
+               return Ycx
+
+       case D_DX,
+               D_BX:
+               return Yrx
+
+       case D_R8, /* not really Yrl */
+               D_R9,
+               D_R10,
+               D_R11,
+               D_R12,
+               D_R13,
+               D_R14,
+               D_R15:
+               if ctxt.Asmode != 64 {
+
+                       return Yxxx
+               }
+               fallthrough
+
+       case D_SP,
+               D_BP,
+               D_SI,
+               D_DI:
+               return Yrl
+
+       case D_F0 + 0:
+               return Yf0
+
+       case D_F0 + 1,
+               D_F0 + 2,
+               D_F0 + 3,
+               D_F0 + 4,
+               D_F0 + 5,
+               D_F0 + 6,
+               D_F0 + 7:
+               return Yrf
+
+       case D_M0 + 0,
+               D_M0 + 1,
+               D_M0 + 2,
+               D_M0 + 3,
+               D_M0 + 4,
+               D_M0 + 5,
+               D_M0 + 6,
+               D_M0 + 7:
+               return Ymr
+
+       case D_X0 + 0,
+               D_X0 + 1,
+               D_X0 + 2,
+               D_X0 + 3,
+               D_X0 + 4,
+               D_X0 + 5,
+               D_X0 + 6,
+               D_X0 + 7,
+               D_X0 + 8,
+               D_X0 + 9,
+               D_X0 + 10,
+               D_X0 + 11,
+               D_X0 + 12,
+               D_X0 + 13,
+               D_X0 + 14,
+               D_X0 + 15:
+               return Yxr
+
+       case D_NONE:
+               return Ynone
+
+       case D_CS:
+               return Ycs
+       case D_SS:
+               return Yss
+       case D_DS:
+               return Yds
+       case D_ES:
+               return Yes
+       case D_FS:
+               return Yfs
+       case D_GS:
+               return Ygs
+       case D_TLS:
+               return Ytls
+
+       case D_GDTR:
+               return Ygdtr
+       case D_IDTR:
+               return Yidtr
+       case D_LDTR:
+               return Yldtr
+       case D_MSW:
+               return Ymsw
+       case D_TASK:
+               return Ytask
+
+       case D_CR + 0:
+               return Ycr0
+       case D_CR + 1:
+               return Ycr1
+       case D_CR + 2:
+               return Ycr2
+       case D_CR + 3:
+               return Ycr3
+       case D_CR + 4:
+               return Ycr4
+       case D_CR + 5:
+               return Ycr5
+       case D_CR + 6:
+               return Ycr6
+       case D_CR + 7:
+               return Ycr7
+       case D_CR + 8:
+               return Ycr8
+
+       case D_DR + 0:
+               return Ydr0
+       case D_DR + 1:
+               return Ydr1
+       case D_DR + 2:
+               return Ydr2
+       case D_DR + 3:
+               return Ydr3
+       case D_DR + 4:
+               return Ydr4
+       case D_DR + 5:
+               return Ydr5
+       case D_DR + 6:
+               return Ydr6
+       case D_DR + 7:
+               return Ydr7
+
+       case D_TR + 0:
+               return Ytr0
+       case D_TR + 1:
+               return Ytr1
+       case D_TR + 2:
+               return Ytr2
+       case D_TR + 3:
+               return Ytr3
+       case D_TR + 4:
+               return Ytr4
+       case D_TR + 5:
+               return Ytr5
+       case D_TR + 6:
+               return Ytr6
+       case D_TR + 7:
+               return Ytr7
+
+       case D_EXTERN,
+               D_STATIC,
+               D_AUTO,
+               D_PARAM:
+               return Ym
+
+       case D_CONST,
+               D_ADDR:
+               if a.Sym == nil {
+                       v = a.Offset
+                       if v == 0 {
+                               return Yi0
+                       }
+                       if v == 1 {
+                               return Yi1
+                       }
+                       if v >= -128 && v <= 127 {
+                               return Yi8
+                       }
+                       l = int32(v)
+                       if int64(l) == v {
+                               return Ys32 /* can sign extend */
+                       }
+                       if v>>32 == 0 {
+                               return Yi32 /* unsigned */
+                       }
+                       return Yi64
+               }
+
+               return Yi32
+
+       case D_BRANCH:
+               return Ybr
+       }
+
+       return Yxxx
+}
+
+func asmidx(ctxt *obj.Link, scale int, index int, base int) {
+       var i int
+
+       switch index {
+       default:
+               goto bad
+
+       case D_NONE:
+               i = 4 << 3
+               goto bas
+
+       case D_R8,
+               D_R9,
+               D_R10,
+               D_R11,
+               D_R12,
+               D_R13,
+               D_R14,
+               D_R15:
+               if ctxt.Asmode != 64 {
+                       goto bad
+               }
+               fallthrough
+
+       case D_AX,
+               D_CX,
+               D_DX,
+               D_BX,
+               D_BP,
+               D_SI,
+               D_DI:
+               i = reg[index] << 3
+               break
+       }
+
+       switch scale {
+       default:
+               goto bad
+
+       case 1:
+               break
+
+       case 2:
+               i |= 1 << 6
+
+       case 4:
+               i |= 2 << 6
+
+       case 8:
+               i |= 3 << 6
+               break
+       }
+
+bas:
+       switch base {
+       default:
+               goto bad
+
+       case D_NONE: /* must be mod=00 */
+               i |= 5
+
+       case D_R8,
+               D_R9,
+               D_R10,
+               D_R11,
+               D_R12,
+               D_R13,
+               D_R14,
+               D_R15:
+               if ctxt.Asmode != 64 {
+                       goto bad
+               }
+               fallthrough
+
+       case D_AX,
+               D_CX,
+               D_DX,
+               D_BX,
+               D_SP,
+               D_BP,
+               D_SI,
+               D_DI:
+               i |= reg[base]
+               break
+       }
+
+       ctxt.Andptr[0] = byte(i)
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return
+
+bad:
+       ctxt.Diag("asmidx: bad address %d/%d/%d", scale, index, base)
+       ctxt.Andptr[0] = 0
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return
+}
+
+func put4(ctxt *obj.Link, v int32) {
+       ctxt.Andptr[0] = byte(v)
+       ctxt.Andptr[1] = byte(v >> 8)
+       ctxt.Andptr[2] = byte(v >> 16)
+       ctxt.Andptr[3] = byte(v >> 24)
+       ctxt.Andptr = ctxt.Andptr[4:]
+}
+
+func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+       var v int64
+       var rel obj.Reloc
+       var r *obj.Reloc
+
+       v = vaddr(ctxt, p, a, &rel)
+       if rel.Siz != 0 {
+               if rel.Siz != 4 {
+                       ctxt.Diag("bad reloc")
+               }
+               r = obj.Addrel(ctxt.Cursym)
+               *r = rel
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+       }
+
+       put4(ctxt, int32(v))
+}
+
+func put8(ctxt *obj.Link, v int64) {
+       ctxt.Andptr[0] = byte(v)
+       ctxt.Andptr[1] = byte(v >> 8)
+       ctxt.Andptr[2] = byte(v >> 16)
+       ctxt.Andptr[3] = byte(v >> 24)
+       ctxt.Andptr[4] = byte(v >> 32)
+       ctxt.Andptr[5] = byte(v >> 40)
+       ctxt.Andptr[6] = byte(v >> 48)
+       ctxt.Andptr[7] = byte(v >> 56)
+       ctxt.Andptr = ctxt.Andptr[8:]
+}
+
+/*
+static void
+relput8(Prog *p, Addr *a)
+{
+       vlong v;
+       Reloc rel, *r;
+
+       v = vaddr(ctxt, p, a, &rel);
+       if(rel.siz != 0) {
+               r = addrel(ctxt->cursym);
+               *r = rel;
+               r->siz = 8;
+               r->off = p->pc + ctxt->andptr - ctxt->and;
+       }
+       put8(ctxt, v);
+}
+*/
+func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 {
+
+       var t int
+       var v int64
+       var s *obj.LSym
+
+       if r != nil {
+               *r = obj.Reloc{}
+       }
+
+       t = int(a.Type)
+       v = a.Offset
+       if t == D_ADDR {
+               t = int(a.Index)
+       }
+       switch t {
+       case D_STATIC,
+               D_EXTERN:
+               s = a.Sym
+               if r == nil {
+                       ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+                       log.Fatalf("reloc")
+               }
+
+               if isextern(s) != 0 {
+                       r.Siz = 4
+                       r.Type = obj.R_ADDR
+               } else {
+
+                       r.Siz = 4
+                       r.Type = obj.R_PCREL
+               }
+
+               r.Off = -1 // caller must fill in
+               r.Sym = s
+               r.Add = v
+               v = 0
+               if s.Type == obj.STLSBSS {
+                       r.Xadd = r.Add - int64(r.Siz)
+                       r.Type = obj.R_TLS
+                       r.Xsym = s
+               }
+
+       case D_INDIR + D_TLS:
+               if r == nil {
+                       ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+                       log.Fatalf("reloc")
+               }
+
+               r.Type = obj.R_TLS_LE
+               r.Siz = 4
+               r.Off = -1 // caller must fill in
+               r.Add = v
+               v = 0
+               break
+       }
+
+       return v
+}
+
+func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) {
+       var v int32
+       var t int
+       var scale int
+       var rel obj.Reloc
+
+       rex &= 0x40 | Rxr
+       v = int32(a.Offset)
+       t = int(a.Type)
+       rel.Siz = 0
+       if a.Index != D_NONE && a.Index != D_TLS {
+               if t < D_INDIR {
+                       switch t {
+                       default:
+                               goto bad
+
+                       case D_EXTERN,
+                               D_STATIC:
+                               if !(isextern(a.Sym) != 0) {
+                                       goto bad
+                               }
+                               t = D_NONE
+                               v = int32(vaddr(ctxt, p, a, &rel))
+
+                       case D_AUTO,
+                               D_PARAM:
+                               t = D_SP
+                               break
+                       }
+               } else {
+
+                       t -= D_INDIR
+               }
+               ctxt.Rexflag |= regrex[int(a.Index)]&Rxx | regrex[t]&Rxb | rex
+               if t == D_NONE {
+                       ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       goto putrelv
+               }
+
+               if v == 0 && rel.Siz == 0 && t != D_BP && t != D_R13 {
+                       ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       return
+               }
+
+               if v >= -128 && v < 128 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, int(a.Scale), int(a.Index), t)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmidx(ctxt, int(a.Scale), int(a.Index), t)
+               goto putrelv
+       }
+
+       if t >= D_AL && t <= D_X0+15 {
+               if v != 0 {
+                       goto bad
+               }
+               ctxt.Andptr[0] = byte(3<<6 | reg[t]<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Rexflag |= regrex[t]&(0x40|Rxb) | rex
+               return
+       }
+
+       scale = int(a.Scale)
+       if t < D_INDIR {
+               switch a.Type {
+               default:
+                       goto bad
+
+               case D_STATIC,
+                       D_EXTERN:
+                       t = D_NONE
+                       v = int32(vaddr(ctxt, p, a, &rel))
+
+               case D_AUTO,
+                       D_PARAM:
+                       t = D_SP
+                       break
+               }
+
+               scale = 1
+       } else {
+
+               t -= D_INDIR
+       }
+       if t == D_TLS {
+               v = int32(vaddr(ctxt, p, a, &rel))
+       }
+
+       ctxt.Rexflag |= regrex[t]&Rxb | rex
+       if t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS {
+               if (a.Sym == nil || !(isextern(a.Sym) != 0)) && t == D_NONE && (a.Type == D_STATIC || a.Type == D_EXTERN) || ctxt.Asmode != 64 {
+                       ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       goto putrelv
+               }
+
+               /* temporary */
+               ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:] /* sib present */
+               ctxt.Andptr[0] = 0<<6 | 4<<3 | 5<<0
+               ctxt.Andptr = ctxt.Andptr[1:] /* DS:d32 */
+               goto putrelv
+       }
+
+       if t == D_SP || t == D_R12 {
+               if v == 0 {
+                       ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, scale, D_NONE, t)
+                       return
+               }
+
+               if v >= -128 && v < 128 {
+                       ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmidx(ctxt, scale, D_NONE, t)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmidx(ctxt, scale, D_NONE, t)
+               goto putrelv
+       }
+
+       if t >= D_AX && t <= D_R15 {
+               if a.Index == D_TLS {
+                       rel = obj.Reloc{}
+                       rel.Type = obj.R_TLS_IE
+                       rel.Siz = 4
+                       rel.Sym = nil
+                       rel.Add = int64(v)
+                       v = 0
+               }
+
+               if v == 0 && rel.Siz == 0 && t != D_BP && t != D_R13 {
+                       ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+               }
+
+               if v >= -128 && v < 128 && rel.Siz == 0 {
+                       ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+                       ctxt.Andptr[1] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[2:]
+                       return
+               }
+
+               ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               goto putrelv
+       }
+
+       goto bad
+
+putrelv:
+       if rel.Siz != 0 {
+               var r *obj.Reloc
+
+               if rel.Siz != 4 {
+                       ctxt.Diag("bad rel")
+                       goto bad
+               }
+
+               r = obj.Addrel(ctxt.Cursym)
+               *r = rel
+               r.Off = int32(ctxt.Curp.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+       }
+
+       put4(ctxt, v)
+       return
+
+bad:
+       ctxt.Diag("asmand: bad address %v", Dconv(p, 0, a))
+       return
+}
+
+func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, ra *obj.Addr) {
+       asmandsz(ctxt, p, a, reg[ra.Type], regrex[ra.Type], 0)
+}
+
+func asmando(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, o int) {
+       asmandsz(ctxt, p, a, o, 0, 0)
+}
+
+func bytereg(a *obj.Addr, t *uint8) {
+       if a.Index == D_NONE && (a.Type >= D_AX && a.Type <= D_R15) {
+               a.Type = D_AL + (a.Type - D_AX)
+               *t = 0
+       }
+}
+
+const (
+       E = 0xff
+)
+
+var ymovtab = []Movtab{
+       /* push */
+       Movtab{APUSHL, Ycs, Ynone, 0, [4]uint8{0x0e, E, 0, 0}},
+       Movtab{APUSHL, Yss, Ynone, 0, [4]uint8{0x16, E, 0, 0}},
+       Movtab{APUSHL, Yds, Ynone, 0, [4]uint8{0x1e, E, 0, 0}},
+       Movtab{APUSHL, Yes, Ynone, 0, [4]uint8{0x06, E, 0, 0}},
+       Movtab{APUSHL, Yfs, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+       Movtab{APUSHL, Ygs, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+       Movtab{APUSHQ, Yfs, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+       Movtab{APUSHQ, Ygs, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+       Movtab{APUSHW, Ycs, Ynone, 0, [4]uint8{Pe, 0x0e, E, 0}},
+       Movtab{APUSHW, Yss, Ynone, 0, [4]uint8{Pe, 0x16, E, 0}},
+       Movtab{APUSHW, Yds, Ynone, 0, [4]uint8{Pe, 0x1e, E, 0}},
+       Movtab{APUSHW, Yes, Ynone, 0, [4]uint8{Pe, 0x06, E, 0}},
+       Movtab{APUSHW, Yfs, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa0, E}},
+       Movtab{APUSHW, Ygs, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa8, E}},
+
+       /* pop */
+       Movtab{APOPL, Ynone, Yds, 0, [4]uint8{0x1f, E, 0, 0}},
+       Movtab{APOPL, Ynone, Yes, 0, [4]uint8{0x07, E, 0, 0}},
+       Movtab{APOPL, Ynone, Yss, 0, [4]uint8{0x17, E, 0, 0}},
+       Movtab{APOPL, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+       Movtab{APOPL, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+       Movtab{APOPQ, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+       Movtab{APOPQ, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+       Movtab{APOPW, Ynone, Yds, 0, [4]uint8{Pe, 0x1f, E, 0}},
+       Movtab{APOPW, Ynone, Yes, 0, [4]uint8{Pe, 0x07, E, 0}},
+       Movtab{APOPW, Ynone, Yss, 0, [4]uint8{Pe, 0x17, E, 0}},
+       Movtab{APOPW, Ynone, Yfs, 0, [4]uint8{Pe, 0x0f, 0xa1, E}},
+       Movtab{APOPW, Ynone, Ygs, 0, [4]uint8{Pe, 0x0f, 0xa9, E}},
+
+       /* mov seg */
+       Movtab{AMOVW, Yes, Yml, 1, [4]uint8{0x8c, 0, 0, 0}},
+       Movtab{AMOVW, Ycs, Yml, 1, [4]uint8{0x8c, 1, 0, 0}},
+       Movtab{AMOVW, Yss, Yml, 1, [4]uint8{0x8c, 2, 0, 0}},
+       Movtab{AMOVW, Yds, Yml, 1, [4]uint8{0x8c, 3, 0, 0}},
+       Movtab{AMOVW, Yfs, Yml, 1, [4]uint8{0x8c, 4, 0, 0}},
+       Movtab{AMOVW, Ygs, Yml, 1, [4]uint8{0x8c, 5, 0, 0}},
+       Movtab{AMOVW, Yml, Yes, 2, [4]uint8{0x8e, 0, 0, 0}},
+       Movtab{AMOVW, Yml, Ycs, 2, [4]uint8{0x8e, 1, 0, 0}},
+       Movtab{AMOVW, Yml, Yss, 2, [4]uint8{0x8e, 2, 0, 0}},
+       Movtab{AMOVW, Yml, Yds, 2, [4]uint8{0x8e, 3, 0, 0}},
+       Movtab{AMOVW, Yml, Yfs, 2, [4]uint8{0x8e, 4, 0, 0}},
+       Movtab{AMOVW, Yml, Ygs, 2, [4]uint8{0x8e, 5, 0, 0}},
+
+       /* mov cr */
+       Movtab{AMOVL, Ycr0, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+       Movtab{AMOVL, Ycr2, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+       Movtab{AMOVL, Ycr3, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+       Movtab{AMOVL, Ycr4, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+       Movtab{AMOVL, Ycr8, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+       Movtab{AMOVQ, Ycr0, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+       Movtab{AMOVQ, Ycr2, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+       Movtab{AMOVQ, Ycr3, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+       Movtab{AMOVQ, Ycr4, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+       Movtab{AMOVQ, Ycr8, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+       Movtab{AMOVL, Yml, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+       Movtab{AMOVL, Yml, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+       Movtab{AMOVL, Yml, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+       Movtab{AMOVL, Yml, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+       Movtab{AMOVL, Yml, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+       Movtab{AMOVQ, Yml, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+       Movtab{AMOVQ, Yml, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+       Movtab{AMOVQ, Yml, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+       Movtab{AMOVQ, Yml, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+       Movtab{AMOVQ, Yml, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+
+       /* mov dr */
+       Movtab{AMOVL, Ydr0, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+       Movtab{AMOVL, Ydr6, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+       Movtab{AMOVL, Ydr7, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+       Movtab{AMOVQ, Ydr0, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+       Movtab{AMOVQ, Ydr6, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+       Movtab{AMOVQ, Ydr7, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+       Movtab{AMOVL, Yml, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+       Movtab{AMOVL, Yml, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+       Movtab{AMOVL, Yml, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+       Movtab{AMOVQ, Yml, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+       Movtab{AMOVQ, Yml, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+       Movtab{AMOVQ, Yml, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+
+       /* mov tr */
+       Movtab{AMOVL, Ytr6, Yml, 3, [4]uint8{0x0f, 0x24, 6, 0}},
+       Movtab{AMOVL, Ytr7, Yml, 3, [4]uint8{0x0f, 0x24, 7, 0}},
+       Movtab{AMOVL, Yml, Ytr6, 4, [4]uint8{0x0f, 0x26, 6, E}},
+       Movtab{AMOVL, Yml, Ytr7, 4, [4]uint8{0x0f, 0x26, 7, E}},
+
+       /* lgdt, sgdt, lidt, sidt */
+       Movtab{AMOVL, Ym, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+       Movtab{AMOVL, Ygdtr, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+       Movtab{AMOVL, Ym, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+       Movtab{AMOVL, Yidtr, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+       Movtab{AMOVQ, Ym, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+       Movtab{AMOVQ, Ygdtr, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+       Movtab{AMOVQ, Ym, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+       Movtab{AMOVQ, Yidtr, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+
+       /* lldt, sldt */
+       Movtab{AMOVW, Yml, Yldtr, 4, [4]uint8{0x0f, 0x00, 2, 0}},
+       Movtab{AMOVW, Yldtr, Yml, 3, [4]uint8{0x0f, 0x00, 0, 0}},
+
+       /* lmsw, smsw */
+       Movtab{AMOVW, Yml, Ymsw, 4, [4]uint8{0x0f, 0x01, 6, 0}},
+       Movtab{AMOVW, Ymsw, Yml, 3, [4]uint8{0x0f, 0x01, 4, 0}},
+
+       /* ltr, str */
+       Movtab{AMOVW, Yml, Ytask, 4, [4]uint8{0x0f, 0x00, 3, 0}},
+       Movtab{AMOVW, Ytask, Yml, 3, [4]uint8{0x0f, 0x00, 1, 0}},
+
+       /* load full pointer */
+       Movtab{AMOVL, Yml, Ycol, 5, [4]uint8{0, 0, 0, 0}},
+       Movtab{AMOVW, Yml, Ycol, 5, [4]uint8{Pe, 0, 0, 0}},
+
+       /* double shift */
+       Movtab{ASHLL, Ycol, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
+       Movtab{ASHRL, Ycol, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
+       Movtab{ASHLQ, Ycol, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
+       Movtab{ASHRQ, Ycol, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
+       Movtab{ASHLW, Ycol, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
+       Movtab{ASHRW, Ycol, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
+
+       /* load TLS base */
+       Movtab{AMOVQ, Ytls, Yrl, 7, [4]uint8{0, 0, 0, 0}},
+       Movtab{0, 0, 0, 0, [4]uint8{}},
+}
+
+func isax(a *obj.Addr) int {
+       switch a.Type {
+       case D_AX,
+               D_AL,
+               D_AH,
+               D_INDIR + D_AX:
+               return 1
+       }
+
+       if a.Index == D_AX {
+               return 1
+       }
+       return 0
+}
+
+func subreg(p *obj.Prog, from int, to int) {
+       if false { /*debug['Q']*/
+               fmt.Printf("\n%v\ts/%v/%v/\n", p, Rconv(from), Rconv(to))
+       }
+
+       if int(p.From.Type) == from {
+               p.From.Type = int16(to)
+       }
+       if int(p.To.Type) == from {
+               p.To.Type = int16(to)
+       }
+
+       if int(p.From.Index) == from {
+               p.From.Index = uint8(to)
+       }
+       if int(p.To.Index) == from {
+               p.To.Index = uint8(to)
+       }
+
+       from += D_INDIR
+       if int(p.From.Type) == from {
+               p.From.Type = int16(to + D_INDIR)
+       }
+       if int(p.To.Type) == from {
+               p.To.Type = int16(to + D_INDIR)
+       }
+
+       if false { /*debug['Q']*/
+               fmt.Printf("%v\n", p)
+       }
+}
+
+func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
+       switch op {
+       case Pm,
+               Pe,
+               Pf2,
+               Pf3:
+               if osize != 1 {
+                       if op != Pm {
+                               ctxt.Andptr[0] = byte(op)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = Pm
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       z++
+                       op = int(o.op[z])
+                       break
+               }
+               fallthrough
+
+       default:
+               if -cap(ctxt.Andptr) == -cap(ctxt.And) || ctxt.And[-cap(ctxt.Andptr)+cap(ctxt.And[:])-1] != Pm {
+                       ctxt.Andptr[0] = Pm
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               break
+       }
+
+       ctxt.Andptr[0] = byte(op)
+       ctxt.Andptr = ctxt.Andptr[1:]
+       return z
+}
+
+func doasm(ctxt *obj.Link, p *obj.Prog) {
+       var o *Optab
+       var q *obj.Prog
+       var pp obj.Prog
+       var t []byte
+       var mo []Movtab
+       var z int
+       var op int
+       var ft int
+       var tt int
+       var xo int
+       var l int
+       var pre int
+       var v int64
+       var rel obj.Reloc
+       var r *obj.Reloc
+       var a *obj.Addr
+
+       ctxt.Curp = p // TODO
+
+       o = opindex[p.As]
+
+       if o == nil {
+               ctxt.Diag("asmins: missing op %v", p)
+               return
+       }
+
+       pre = prefixof(ctxt, &p.From)
+       if pre != 0 {
+               ctxt.Andptr[0] = byte(pre)
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+       pre = prefixof(ctxt, &p.To)
+       if pre != 0 {
+               ctxt.Andptr[0] = byte(pre)
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+
+       if p.Ft == 0 {
+               p.Ft = uint8(oclass(ctxt, &p.From))
+       }
+       if p.Tt == 0 {
+               p.Tt = uint8(oclass(ctxt, &p.To))
+       }
+
+       ft = int(p.Ft) * Ymax
+       tt = int(p.Tt) * Ymax
+
+       t = o.ytab
+       if t == nil {
+               ctxt.Diag("asmins: noproto %v", p)
+               return
+       }
+
+       xo = bool2int(o.op[0] == 0x0f)
+       for z = 0; t[0] != 0; (func() { z += int(t[3]) + xo; t = t[4:] })() {
+               if ycover[ft+int(t[0])] != 0 {
+                       if ycover[tt+int(t[1])] != 0 {
+                               goto found
+                       }
+               }
+       }
+       goto domov
+
+found:
+       switch o.prefix {
+       case Pq: /* 16 bit escape and opcode escape */
+               ctxt.Andptr[0] = Pe
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pq3: /* 16 bit escape, Rex.w, and opcode escape */
+               ctxt.Andptr[0] = Pe
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = Pw
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pf2, /* xmm opcode escape */
+               Pf3:
+               ctxt.Andptr[0] = byte(o.prefix)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pm: /* opcode escape */
+               ctxt.Andptr[0] = Pm
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pe: /* 16 bit escape */
+               ctxt.Andptr[0] = Pe
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Pw: /* 64-bit escape */
+               if p.Mode != 64 {
+
+                       ctxt.Diag("asmins: illegal 64: %v", p)
+               }
+               ctxt.Rexflag |= Pw
+
+       case Pb: /* botch */
+               bytereg(&p.From, &p.Ft)
+
+               bytereg(&p.To, &p.Tt)
+
+       case P32: /* 32 bit but illegal if 64-bit mode */
+               if p.Mode == 64 {
+
+                       ctxt.Diag("asmins: illegal in 64-bit mode: %v", p)
+               }
+
+       case Py: /* 64-bit only, no prefix */
+               if p.Mode != 64 {
+
+                       ctxt.Diag("asmins: illegal in %d-bit mode: %v", p.Mode, p)
+               }
+               break
+       }
+
+       if z >= len(o.op) {
+               log.Fatalf("asmins bad table %v", p)
+       }
+       op = int(o.op[z])
+       if op == 0x0f {
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               z++
+               op = int(o.op[z])
+       }
+
+       switch t[2] {
+       default:
+               ctxt.Diag("asmins: unknown z %d %v", t[2], p)
+               return
+
+       case Zpseudo:
+               break
+
+       case Zlit:
+               for ; ; z++ {
+                       op = int(o.op[z])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case Zlitm_r:
+               for ; ; z++ {
+                       op = int(o.op[z])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case Zmb_r:
+               bytereg(&p.From, &p.Ft)
+               fallthrough
+
+               /* fall through */
+       case Zm_r:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case Zm2_r:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(o.op[z+1])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case Zm_r_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case Zm_r_xm_nr:
+               ctxt.Rexflag = 0
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case Zm_r_i_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.From, &p.To)
+               ctxt.Andptr[0] = byte(p.To.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zm_r_3d:
+               ctxt.Andptr[0] = 0x0f
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = 0x0f
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.From, &p.To)
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zibm_r:
+               for {
+                       tmp1 := z
+                       z++
+                       op = int(o.op[tmp1])
+                       if !(op != 0) {
+                               break
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               asmand(ctxt, p, &p.From, &p.To)
+               ctxt.Andptr[0] = byte(p.To.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zaut_r:
+               ctxt.Andptr[0] = 0x8d
+               ctxt.Andptr = ctxt.Andptr[1:] /* leal */
+               if p.From.Type != D_ADDR {
+                       ctxt.Diag("asmins: Zaut sb type ADDR")
+               }
+               p.From.Type = int16(p.From.Index)
+               p.From.Index = D_NONE
+               asmand(ctxt, p, &p.From, &p.To)
+               p.From.Index = uint8(p.From.Type)
+               p.From.Type = D_ADDR
+
+       case Zm_o:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.From, int(o.op[z+1]))
+
+       case Zr_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, &p.From)
+
+       case Zr_m_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.To, &p.From)
+
+       case Zr_m_xm_nr:
+               ctxt.Rexflag = 0
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.To, &p.From)
+
+       case Zr_m_i_xm:
+               mediaop(ctxt, o, op, int(t[3]), z)
+               asmand(ctxt, p, &p.To, &p.From)
+               ctxt.Andptr[0] = byte(p.From.Offset)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.To, int(o.op[z+1]))
+
+       case Zcallindreg:
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc)
+               r.Type = obj.R_CALLIND
+               r.Siz = 0
+               fallthrough
+
+               // fallthrough
+       case Zo_m64:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmandsz(ctxt, p, &p.To, int(o.op[z+1]), 0, 1)
+
+       case Zm_ibo:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.From, int(o.op[z+1]))
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.To, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zibo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.To, int(o.op[z+1]))
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zibo_m_xm:
+               z = mediaop(ctxt, o, op, int(t[3]), z)
+               asmando(ctxt, p, &p.To, int(o.op[z+1]))
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Z_ib,
+               Zib_:
+               if t[2] == Zib_ {
+                       a = &p.From
+               } else {
+
+                       a = &p.To
+               }
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, a, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zib_rp:
+               ctxt.Rexflag |= regrex[p.To.Type] & (Rxb | 0x40)
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zil_rp:
+               ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, &p.From, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, &p.From)
+               }
+
+       case Zo_iw:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if p.From.Type != D_NONE {
+                       v = vaddr(ctxt, p, &p.From, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case Ziq_rp:
+               v = vaddr(ctxt, p, &p.From, &rel)
+               l = int(v >> 32)
+               if l == 0 && rel.Siz != 8 {
+                       //p->mark |= 0100;
+                       //print("zero: %llux %P\n", v, p);
+                       ctxt.Rexflag &^= (0x40 | Rxw)
+
+                       ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+                       ctxt.Andptr[0] = byte(0xb8 + reg[p.To.Type])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       if rel.Type != 0 {
+                               r = obj.Addrel(ctxt.Cursym)
+                               *r = rel
+                               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+                       }
+
+                       put4(ctxt, int32(v))
+               } else if l == -1 && uint64(v)&(uint64(1)<<31) != 0 { /* sign extend */
+
+                       //p->mark |= 0100;
+                       //print("sign: %llux %P\n", v, p);
+                       ctxt.Andptr[0] = 0xc7
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+                       asmando(ctxt, p, &p.To, 0)
+                       put4(ctxt, int32(v)) /* need all 8 */
+               } else {
+
+                       //print("all: %llux %P\n", v, p);
+                       ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+
+                       ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       if rel.Type != 0 {
+                               r = obj.Addrel(ctxt.Cursym)
+                               *r = rel
+                               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+                       }
+
+                       put8(ctxt, v)
+               }
+
+       case Zib_rr:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, &p.To)
+               ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Z_il,
+               Zil_:
+               if t[2] == Zil_ {
+                       a = &p.From
+               } else {
+
+                       a = &p.To
+               }
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, a, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, a)
+               }
+
+       case Zm_ilo,
+               Zilo_m:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if t[2] == Zilo_m {
+                       a = &p.From
+                       asmando(ctxt, p, &p.To, int(o.op[z+1]))
+               } else {
+
+                       a = &p.To
+                       asmando(ctxt, p, &p.From, int(o.op[z+1]))
+               }
+
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, a, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, a)
+               }
+
+       case Zil_rr:
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, &p.To)
+               if o.prefix == Pe {
+                       v = vaddr(ctxt, p, &p.From, nil)
+                       ctxt.Andptr[0] = byte(v)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else {
+
+                       relput4(ctxt, p, &p.From)
+               }
+
+       case Z_rp:
+               ctxt.Rexflag |= regrex[p.To.Type] & (Rxb | 0x40)
+               ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zrp_:
+               ctxt.Rexflag |= regrex[p.From.Type] & (Rxb | 0x40)
+               ctxt.Andptr[0] = byte(op + reg[p.From.Type])
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+       case Zclr:
+               ctxt.Rexflag &^= Pw
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmand(ctxt, p, &p.To, &p.To)
+
+       case Zcall:
+               if p.To.Sym == nil {
+                       ctxt.Diag("call without target")
+                       log.Fatalf("bad code")
+               }
+
+               ctxt.Andptr[0] = byte(op)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               r.Sym = p.To.Sym
+               r.Add = p.To.Offset
+               r.Type = obj.R_CALL
+               r.Siz = 4
+               put4(ctxt, 0)
+
+               // TODO: jump across functions needs reloc
+       case Zbr,
+               Zjmp,
+               Zloop:
+               if p.To.Sym != nil {
+
+                       if t[2] != Zjmp {
+                               ctxt.Diag("branch to ATEXT")
+                               log.Fatalf("bad code")
+                       }
+
+                       ctxt.Andptr[0] = byte(o.op[z+1])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       r = obj.Addrel(ctxt.Cursym)
+                       r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+                       r.Sym = p.To.Sym
+                       r.Type = obj.R_PCREL
+                       r.Siz = 4
+                       put4(ctxt, 0)
+                       break
+               }
+
+               // Assumes q is in this function.
+               // TODO: Check in input, preserve in brchain.
+
+               // Fill in backward jump now.
+               q = p.Pcond
+
+               if q == nil {
+                       ctxt.Diag("jmp/branch/loop without target")
+                       log.Fatalf("bad code")
+               }
+
+               if p.Back&1 != 0 {
+                       v = q.Pc - (p.Pc + 2)
+                       if v >= -128 {
+                               if p.As == AJCXZL {
+                                       ctxt.Andptr[0] = 0x67
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                               }
+                               ctxt.Andptr[0] = byte(op)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       } else if t[2] == Zloop {
+                               ctxt.Diag("loop too far: %v", p)
+                       } else {
+
+                               v -= 5 - 2
+                               if t[2] == Zbr {
+                                       ctxt.Andptr[0] = 0x0f
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                                       v--
+                               }
+
+                               ctxt.Andptr[0] = byte(o.op[z+1])
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 8)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 16)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 24)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+
+                       break
+               }
+
+               // Annotate target; will fill in later.
+               p.Forwd = q.Comefrom
+
+               q.Comefrom = p
+               if p.Back&2 != 0 { // short
+                       if p.As == AJCXZL {
+                               ctxt.Andptr[0] = 0x67
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = byte(op)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               } else if t[2] == Zloop {
+                       ctxt.Diag("loop too far: %v", p)
+               } else {
+
+                       if t[2] == Zbr {
+                               ctxt.Andptr[0] = 0x0f
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+                       ctxt.Andptr[0] = byte(o.op[z+1])
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+               break
+
+       /*
+               v = q->pc - p->pc - 2;
+               if((v >= -128 && v <= 127) || p->pc == -1 || q->pc == -1) {
+                       *ctxt->andptr++ = op;
+                       *ctxt->andptr++ = v;
+               } else {
+                       v -= 5-2;
+                       if(t[2] == Zbr) {
+                               *ctxt->andptr++ = 0x0f;
+                               v--;
+                       }
+                       *ctxt->andptr++ = o->op[z+1];
+                       *ctxt->andptr++ = v;
+                       *ctxt->andptr++ = v>>8;
+                       *ctxt->andptr++ = v>>16;
+                       *ctxt->andptr++ = v>>24;
+               }
+       */
+
+       case Zbyte:
+               v = vaddr(ctxt, p, &p.From, &rel)
+               if rel.Siz != 0 {
+                       rel.Siz = uint8(op)
+                       r = obj.Addrel(ctxt.Cursym)
+                       *r = rel
+                       r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+               }
+
+               ctxt.Andptr[0] = byte(v)
+               ctxt.Andptr = ctxt.Andptr[1:]
+               if op > 1 {
+                       ctxt.Andptr[0] = byte(v >> 8)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       if op > 2 {
+                               ctxt.Andptr[0] = byte(v >> 16)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(v >> 24)
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               if op > 4 {
+                                       ctxt.Andptr[0] = byte(v >> 32)
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                                       ctxt.Andptr[0] = byte(v >> 40)
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                                       ctxt.Andptr[0] = byte(v >> 48)
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                                       ctxt.Andptr[0] = byte(v >> 56)
+                                       ctxt.Andptr = ctxt.Andptr[1:]
+                               }
+                       }
+               }
+
+               break
+       }
+
+       return
+
+domov:
+       for mo = ymovtab; mo[0].as != 0; mo = mo[1:] {
+               if p.As == mo[0].as {
+                       if ycover[ft+int(mo[0].ft)] != 0 {
+                               if ycover[tt+int(mo[0].tt)] != 0 {
+                                       t = mo[0].op[:]
+                                       goto mfound
+                               }
+                       }
+               }
+       }
+
+bad:
+       if p.Mode != 64 {
+               /*
+                * here, the assembly has failed.
+                * if its a byte instruction that has
+                * unaddressable registers, try to
+                * exchange registers and reissue the
+                * instruction with the operands renamed.
+                */
+               pp = *p
+
+               z = int(p.From.Type)
+               if z >= D_BP && z <= D_DI {
+                       if isax(&p.To) != 0 || p.To.Type == D_NONE {
+                               // We certainly don't want to exchange
+                               // with AX if the op is MUL or DIV.
+                               ctxt.Andptr[0] = 0x87
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+                               asmando(ctxt, p, &p.From, reg[D_BX])
+                               subreg(&pp, z, D_BX)
+                               doasm(ctxt, &pp)
+                               ctxt.Andptr[0] = 0x87
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+                               asmando(ctxt, p, &p.From, reg[D_BX])
+                       } else {
+
+                               ctxt.Andptr[0] = byte(0x90 + reg[z])
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+                               subreg(&pp, z, D_AX)
+                               doasm(ctxt, &pp)
+                               ctxt.Andptr[0] = byte(0x90 + reg[z])
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+                       }
+
+                       return
+               }
+
+               z = int(p.To.Type)
+               if z >= D_BP && z <= D_DI {
+                       if isax(&p.From) != 0 {
+                               ctxt.Andptr[0] = 0x87
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+                               asmando(ctxt, p, &p.To, reg[D_BX])
+                               subreg(&pp, z, D_BX)
+                               doasm(ctxt, &pp)
+                               ctxt.Andptr[0] = 0x87
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+                               asmando(ctxt, p, &p.To, reg[D_BX])
+                       } else {
+
+                               ctxt.Andptr[0] = byte(0x90 + reg[z])
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+                               subreg(&pp, z, D_AX)
+                               doasm(ctxt, &pp)
+                               ctxt.Andptr[0] = byte(0x90 + reg[z])
+                               ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+                       }
+
+                       return
+               }
+       }
+
+       ctxt.Diag("doasm: notfound from=%x to=%x %v", uint16(p.From.Type), uint16(p.To.Type), p)
+       return
+
+mfound:
+       switch mo[0].code {
+       default:
+               ctxt.Diag("asmins: unknown mov %d %v", mo[0].code, p)
+
+       case 0: /* lit */
+               for z = 0; t[z] != E; z++ {
+
+                       ctxt.Andptr[0] = t[z]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+
+       case 1: /* r,m */
+               ctxt.Andptr[0] = t[0]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmando(ctxt, p, &p.To, int(t[1]))
+
+       case 2: /* m,r */
+               ctxt.Andptr[0] = t[0]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               asmando(ctxt, p, &p.From, int(t[1]))
+
+       case 3: /* r,m - 2op */
+               ctxt.Andptr[0] = t[0]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = t[1]
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.To, int(t[2]))
+               ctxt.Rexflag |= regrex[p.From.Type] & (Rxr | 0x40)
+
+       case 4: /* m,r - 2op */
+               ctxt.Andptr[0] = t[0]
+               ctxt.Andptr = ctxt.Andptr[1:]
+
+               ctxt.Andptr[0] = t[1]
+               ctxt.Andptr = ctxt.Andptr[1:]
+               asmando(ctxt, p, &p.From, int(t[2]))
+               ctxt.Rexflag |= regrex[p.To.Type] & (Rxr | 0x40)
+
+       case 5: /* load full pointer, trash heap */
+               if t[0] != 0 {
+
+                       ctxt.Andptr[0] = t[0]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+               }
+               switch p.To.Index {
+               default:
+                       goto bad
+
+               case D_DS:
+                       ctxt.Andptr[0] = 0xc5
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_SS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb2
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_ES:
+                       ctxt.Andptr[0] = 0xc4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_FS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_GS:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = 0xb5
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       break
+               }
+
+               asmand(ctxt, p, &p.From, &p.To)
+
+       case 6: /* double shift */
+               if t[0] == Pw {
+
+                       if p.Mode != 64 {
+                               ctxt.Diag("asmins: illegal 64: %v", p)
+                       }
+                       ctxt.Rexflag |= Pw
+                       t = t[1:]
+               } else if t[0] == Pe {
+                       ctxt.Andptr[0] = Pe
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       t = t[1:]
+               }
+
+               z = int(p.From.Type)
+               switch z {
+               default:
+                       goto bad
+
+               case D_CONST:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = t[0]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmandsz(ctxt, p, &p.To, reg[int(p.From.Index)], regrex[int(p.From.Index)], 0)
+                       ctxt.Andptr[0] = byte(p.From.Offset)
+                       ctxt.Andptr = ctxt.Andptr[1:]
+
+               case D_CL,
+                       D_CX:
+                       ctxt.Andptr[0] = 0x0f
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Andptr[0] = t[1]
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmandsz(ctxt, p, &p.To, reg[int(p.From.Index)], regrex[int(p.From.Index)], 0)
+                       break
+               }
+
+               // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
+       // where you load the TLS base register into a register and then index off that
+       // register to access the actual TLS variables. Systems that allow direct TLS access
+       // are handled in prefixof above and should not be listed here.
+       case 7: /* mov tls, r */
+               switch ctxt.Headtype {
+
+               default:
+                       log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype))
+
+               case obj.Hplan9:
+                       if ctxt.Plan9privates == nil {
+                               ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+                       }
+                       pp.From = obj.Addr{}
+                       pp.From.Type = D_EXTERN
+                       pp.From.Sym = ctxt.Plan9privates
+                       pp.From.Offset = 0
+                       pp.From.Index = D_NONE
+                       ctxt.Rexflag |= Pw
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, &p.To)
+
+                       // TLS base is 0(FS).
+               case obj.Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
+                       pp.From = p.From
+
+                       pp.From.Type = D_INDIR + D_NONE
+                       pp.From.Offset = 0
+                       pp.From.Index = D_NONE
+                       pp.From.Scale = 0
+                       ctxt.Rexflag |= Pw
+                       ctxt.Andptr[0] = 0x64
+                       ctxt.Andptr = ctxt.Andptr[1:] // FS
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, &p.To)
+
+                       // Windows TLS base is always 0x28(GS).
+               case obj.Hwindows:
+                       pp.From = p.From
+
+                       pp.From.Type = D_INDIR + D_GS
+                       pp.From.Offset = 0x28
+                       pp.From.Index = D_NONE
+                       pp.From.Scale = 0
+                       ctxt.Rexflag |= Pw
+                       ctxt.Andptr[0] = 0x65
+                       ctxt.Andptr = ctxt.Andptr[1:] // GS
+                       ctxt.Andptr[0] = 0x8B
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       asmand(ctxt, p, &pp.From, &p.To)
+                       break
+               }
+
+               break
+       }
+}
+
+var naclret = []uint8{
+       0x5e, // POPL SI
+       // 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
+       0x83,
+       0xe6,
+       0xe0, // ANDL $~31, SI
+       0x4c,
+       0x01,
+       0xfe, // ADDQ R15, SI
+       0xff,
+       0xe6, // JMP SI
+}
+
+var naclspfix = []uint8{0x4c, 0x01, 0xfc} // ADDQ R15, SP
+
+var naclbpfix = []uint8{0x4c, 0x01, 0xfd} // ADDQ R15, BP
+
+var naclmovs = []uint8{
+       0x89,
+       0xf6, // MOVL SI, SI
+       0x49,
+       0x8d,
+       0x34,
+       0x37, // LEAQ (R15)(SI*1), SI
+       0x89,
+       0xff, // MOVL DI, DI
+       0x49,
+       0x8d,
+       0x3c,
+       0x3f, // LEAQ (R15)(DI*1), DI
+}
+
+var naclstos = []uint8{
+       0x89,
+       0xff, // MOVL DI, DI
+       0x49,
+       0x8d,
+       0x3c,
+       0x3f, // LEAQ (R15)(DI*1), DI
+}
+
+func nacltrunc(ctxt *obj.Link, reg int) {
+       if reg >= D_R8 {
+               ctxt.Andptr[0] = 0x45
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+       reg = (reg - D_AX) & 7
+       ctxt.Andptr[0] = 0x89
+       ctxt.Andptr = ctxt.Andptr[1:]
+       ctxt.Andptr[0] = byte(3<<6 | reg<<3 | reg)
+       ctxt.Andptr = ctxt.Andptr[1:]
+}
+
+func asmins(ctxt *obj.Link, p *obj.Prog) {
+       var i int
+       var n int
+       var np int
+       var c int
+       var and0 []byte
+       var r *obj.Reloc
+
+       ctxt.Andptr = ctxt.And[:]
+       ctxt.Asmode = int(p.Mode)
+
+       if p.As == AUSEFIELD {
+               r = obj.Addrel(ctxt.Cursym)
+               r.Off = 0
+               r.Siz = 0
+               r.Sym = p.From.Sym
+               r.Type = obj.R_USEFIELD
+               return
+       }
+
+       if ctxt.Headtype == obj.Hnacl {
+               if p.As == AREP {
+                       ctxt.Rep++
+                       return
+               }
+
+               if p.As == AREPN {
+                       ctxt.Repn++
+                       return
+               }
+
+               if p.As == ALOCK {
+                       ctxt.Lock++
+                       return
+               }
+
+               if p.As != ALEAQ && p.As != ALEAL {
+                       if p.From.Index != D_NONE && p.From.Scale > 0 {
+                               nacltrunc(ctxt, int(p.From.Index))
+                       }
+                       if p.To.Index != D_NONE && p.To.Scale > 0 {
+                               nacltrunc(ctxt, int(p.To.Index))
+                       }
+               }
+
+               switch p.As {
+               case ARET:
+                       copy(ctxt.Andptr, naclret)
+                       ctxt.Andptr = ctxt.Andptr[len(naclret):]
+                       return
+
+               case ACALL,
+                       AJMP:
+                       if D_AX <= p.To.Type && p.To.Type <= D_DI {
+                               // ANDL $~31, reg
+                               ctxt.Andptr[0] = 0x83
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_AX))
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = 0xe0
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               // ADDQ R15, reg
+                               ctxt.Andptr[0] = 0x4c
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               ctxt.Andptr[0] = 0x01
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(0xf8 | (p.To.Type - D_AX))
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+
+                       if D_R8 <= p.To.Type && p.To.Type <= D_R15 {
+                               // ANDL $~31, reg
+                               ctxt.Andptr[0] = 0x41
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               ctxt.Andptr[0] = 0x83
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_R8))
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = 0xe0
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               // ADDQ R15, reg
+                               ctxt.Andptr[0] = 0x4d
+                               ctxt.Andptr = ctxt.Andptr[1:]
+
+                               ctxt.Andptr[0] = 0x01
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                               ctxt.Andptr[0] = byte(0xf8 | (p.To.Type - D_R8))
+                               ctxt.Andptr = ctxt.Andptr[1:]
+                       }
+
+               case AINT:
+                       ctxt.Andptr[0] = 0xf4
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       return
+
+               case ASCASB,
+                       ASCASW,
+                       ASCASL,
+                       ASCASQ,
+                       ASTOSB,
+                       ASTOSW,
+                       ASTOSL,
+                       ASTOSQ:
+                       copy(ctxt.Andptr, naclstos)
+                       ctxt.Andptr = ctxt.Andptr[len(naclstos):]
+
+               case AMOVSB,
+                       AMOVSW,
+                       AMOVSL,
+                       AMOVSQ:
+                       copy(ctxt.Andptr, naclmovs)
+                       ctxt.Andptr = ctxt.Andptr[len(naclmovs):]
+                       break
+               }
+
+               if ctxt.Rep != 0 {
+                       ctxt.Andptr[0] = 0xf3
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Rep = 0
+               }
+
+               if ctxt.Repn != 0 {
+                       ctxt.Andptr[0] = 0xf2
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Repn = 0
+               }
+
+               if ctxt.Lock != 0 {
+                       ctxt.Andptr[0] = 0xf0
+                       ctxt.Andptr = ctxt.Andptr[1:]
+                       ctxt.Lock = 0
+               }
+       }
+
+       ctxt.Rexflag = 0
+       and0 = ctxt.Andptr
+       ctxt.Asmode = int(p.Mode)
+       doasm(ctxt, p)
+       if ctxt.Rexflag != 0 {
+               /*
+                * as befits the whole approach of the architecture,
+                * the rex prefix must appear before the first opcode byte
+                * (and thus after any 66/67/f2/f3/26/2e/3e prefix bytes, but
+                * before the 0f opcode escape!), or it might be ignored.
+                * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'.
+                */
+               if p.Mode != 64 {
+
+                       ctxt.Diag("asmins: illegal in mode %d: %v", p.Mode, p)
+               }
+               n = -cap(ctxt.Andptr) + cap(and0)
+               for np = 0; np < n; np++ {
+                       c = int(and0[np])
+                       if c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26 {
+                               break
+                       }
+               }
+
+               copy(and0[np+1:], and0[np:n])
+               and0[np] = byte(0x40 | ctxt.Rexflag)
+               ctxt.Andptr = ctxt.Andptr[1:]
+       }
+
+       n = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+       for i = len(ctxt.Cursym.R) - 1; i >= 0; i-- {
+               r = &ctxt.Cursym.R[i:][0]
+               if int64(r.Off) < p.Pc {
+                       break
+               }
+               if ctxt.Rexflag != 0 {
+                       r.Off++
+               }
+               if r.Type == obj.R_PCREL || r.Type == obj.R_CALL {
+                       r.Add -= p.Pc + int64(n) - (int64(r.Off) + int64(r.Siz))
+               }
+       }
+
+       if ctxt.Headtype == obj.Hnacl && p.As != ACMPL && p.As != ACMPQ {
+               switch p.To.Type {
+               case D_SP:
+                       copy(ctxt.Andptr, naclspfix)
+                       ctxt.Andptr = ctxt.Andptr[len(naclspfix):]
+
+               case D_BP:
+                       copy(ctxt.Andptr, naclbpfix)
+                       ctxt.Andptr = ctxt.Andptr[len(naclbpfix):]
+                       break
+               }
+       }
+}
diff --git a/src/cmd/internal/obj/x86/list6.go b/src/cmd/internal/obj/x86/list6.go
new file mode 100644 (file)
index 0000000..df061c7
--- /dev/null
@@ -0,0 +1,324 @@
+// Inferno utils/6c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.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.
+
+package x86
+
+import (
+       "cmd/internal/obj"
+       "fmt"
+)
+
+//
+// Format conversions
+//     %A int          Opcodes (instruction mnemonics)
+//
+//     %D Addr*        Addresses (instruction operands)
+//             Flags: "%lD": seperate the high and low words of a constant by "-"
+//
+//     %P Prog*        Instructions
+//
+//     %R int          Registers
+//
+//     %$ char*        String constant addresses (for internal use only)
+
+const (
+       STRINGSZ = 1000
+)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+       var str string
+       var fp string
+
+       switch p.As {
+       case ADATA:
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, 0, &p.To))
+
+       case ATEXT:
+               if p.From.Scale != 0 {
+                       str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, fmtLong, &p.To))
+                       break
+               }
+
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+
+       default:
+               str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+               break
+       }
+
+       fp += str
+       return fp
+}
+
+func Aconv(i int) string {
+       var fp string
+
+       fp += Anames[i]
+       return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+       var str string
+       var s string
+       var fp string
+
+       var i int
+
+       i = int(a.Type)
+
+       if flag&fmtLong != 0 /*untyped*/ {
+               if i == D_CONST {
+                       str = fmt.Sprintf("$%d-%d", a.Offset&0xffffffff, a.Offset>>32)
+               } else {
+
+                       // ATEXT dst is not constant
+                       str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+               }
+
+               goto brk
+       }
+
+       if i >= D_INDIR {
+               if a.Offset != 0 {
+                       str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(i-D_INDIR))
+               } else {
+
+                       str = fmt.Sprintf("(%v)", Rconv(i-D_INDIR))
+               }
+               goto brk
+       }
+
+       switch i {
+       default:
+               if a.Offset != 0 {
+                       str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(i))
+               } else {
+
+                       str = fmt.Sprintf("%v", Rconv(i))
+               }
+
+       case D_NONE:
+               str = ""
+
+       case D_BRANCH:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+               } else if p != nil && p.Pcond != nil {
+                       str = fmt.Sprintf("%d", p.Pcond.Pc)
+               } else if a.U.Branch != nil {
+                       str = fmt.Sprintf("%d", a.U.Branch.Pc)
+               } else {
+
+                       str = fmt.Sprintf("%d(PC)", a.Offset)
+               }
+
+       case D_EXTERN:
+               str = fmt.Sprintf("%s+%d(SB)", a.Sym.Name, a.Offset)
+
+       case D_STATIC:
+               str = fmt.Sprintf("%s<>+%d(SB)", a.Sym.Name, a.Offset)
+
+       case D_AUTO:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s+%d(SP)", a.Sym.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%d(SP)", a.Offset)
+               }
+
+       case D_PARAM:
+               if a.Sym != nil {
+                       str = fmt.Sprintf("%s+%d(FP)", a.Sym.Name, a.Offset)
+               } else {
+
+                       str = fmt.Sprintf("%d(FP)", a.Offset)
+               }
+
+       case D_CONST:
+               str = fmt.Sprintf("$%d", a.Offset)
+
+       case D_FCONST:
+               str = fmt.Sprintf("$(%.17g)", a.U.Dval)
+
+       case D_SCONST:
+               str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+
+       case D_ADDR:
+               a.Type = int16(a.Index)
+               a.Index = D_NONE
+               str = fmt.Sprintf("$%v", Dconv(p, 0, a))
+               a.Index = uint8(a.Type)
+               a.Type = D_ADDR
+               goto conv
+       }
+
+brk:
+       if a.Index != D_NONE {
+               s = fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
+               str += s
+       }
+
+conv:
+       fp += str
+       return fp
+}
+
+var Register = []string{
+       "AL", /* [D_AL] */
+       "CL",
+       "DL",
+       "BL",
+       "SPB",
+       "BPB",
+       "SIB",
+       "DIB",
+       "R8B",
+       "R9B",
+       "R10B",
+       "R11B",
+       "R12B",
+       "R13B",
+       "R14B",
+       "R15B",
+       "AX", /* [D_AX] */
+       "CX",
+       "DX",
+       "BX",
+       "SP",
+       "BP",
+       "SI",
+       "DI",
+       "R8",
+       "R9",
+       "R10",
+       "R11",
+       "R12",
+       "R13",
+       "R14",
+       "R15",
+       "AH",
+       "CH",
+       "DH",
+       "BH",
+       "F0", /* [D_F0] */
+       "F1",
+       "F2",
+       "F3",
+       "F4",
+       "F5",
+       "F6",
+       "F7",
+       "M0",
+       "M1",
+       "M2",
+       "M3",
+       "M4",
+       "M5",
+       "M6",
+       "M7",
+       "X0",
+       "X1",
+       "X2",
+       "X3",
+       "X4",
+       "X5",
+       "X6",
+       "X7",
+       "X8",
+       "X9",
+       "X10",
+       "X11",
+       "X12",
+       "X13",
+       "X14",
+       "X15",
+       "CS", /* [D_CS] */
+       "SS",
+       "DS",
+       "ES",
+       "FS",
+       "GS",
+       "GDTR", /* [D_GDTR] */
+       "IDTR", /* [D_IDTR] */
+       "LDTR", /* [D_LDTR] */
+       "MSW",  /* [D_MSW] */
+       "TASK", /* [D_TASK] */
+       "CR0",  /* [D_CR] */
+       "CR1",
+       "CR2",
+       "CR3",
+       "CR4",
+       "CR5",
+       "CR6",
+       "CR7",
+       "CR8",
+       "CR9",
+       "CR10",
+       "CR11",
+       "CR12",
+       "CR13",
+       "CR14",
+       "CR15",
+       "DR0", /* [D_DR] */
+       "DR1",
+       "DR2",
+       "DR3",
+       "DR4",
+       "DR5",
+       "DR6",
+       "DR7",
+       "TR0", /* [D_TR] */
+       "TR1",
+       "TR2",
+       "TR3",
+       "TR4",
+       "TR5",
+       "TR6",
+       "TR7",
+       "TLS",  /* [D_TLS] */
+       "NONE", /* [D_NONE] */
+}
+
+func Rconv(r int) string {
+       var str string
+       var fp string
+
+       if r >= D_AL && r <= D_NONE {
+               str = fmt.Sprintf("%s", Register[r-D_AL])
+       } else {
+
+               str = fmt.Sprintf("gok(%d)", r)
+       }
+
+       fp += str
+       return fp
+}
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
new file mode 100644 (file)
index 0000000..1b7c119
--- /dev/null
@@ -0,0 +1,1217 @@
+// Inferno utils/6l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.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.
+
+package x86
+
+import (
+       "cmd/internal/obj"
+       "encoding/binary"
+       "fmt"
+       "log"
+       "math"
+)
+
+var zprg = obj.Prog{
+       Back: 2,
+       As:   AGOK,
+       From: obj.Addr{
+               Type:  D_NONE,
+               Index: D_NONE,
+       },
+       To: obj.Addr{
+               Type:  D_NONE,
+               Index: D_NONE,
+       },
+}
+
+func nopout(p *obj.Prog) {
+       p.As = ANOP
+       p.From.Type = D_NONE
+       p.To.Type = D_NONE
+}
+
+func symtype(a *obj.Addr) int {
+       var t int
+
+       t = int(a.Type)
+       if t == D_ADDR {
+               t = int(a.Index)
+       }
+       return t
+}
+
+func isdata(p *obj.Prog) bool {
+       return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+       return p.As == ACALL
+}
+
+func datasize(p *obj.Prog) int {
+       return int(p.From.Scale)
+}
+
+func textflag(p *obj.Prog) int {
+       return int(p.From.Scale)
+}
+
+func settextflag(p *obj.Prog, f int) {
+       p.From.Scale = int8(f)
+}
+
+func canuselocaltls(ctxt *obj.Link) int {
+       switch ctxt.Headtype {
+       case obj.Hplan9,
+               obj.Hwindows:
+               return 0
+       }
+
+       return 1
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+       var literal string
+       var s *obj.LSym
+       var q *obj.Prog
+
+       // Thread-local storage references use the TLS pseudo-register.
+       // As a register, TLS refers to the thread-local storage base, and it
+       // can only be loaded into another register:
+       //
+       //         MOVQ TLS, AX
+       //
+       // An offset from the thread-local storage base is written off(reg)(TLS*1).
+       // Semantically it is off(reg), but the (TLS*1) annotation marks this as
+       // indexing from the loaded TLS base. This emits a relocation so that
+       // if the linker needs to adjust the offset, it can. For example:
+       //
+       //         MOVQ TLS, AX
+       //         MOVQ 8(AX)(TLS*1), CX // load m into CX
+       //
+       // On systems that support direct access to the TLS memory, this
+       // pair of instructions can be reduced to a direct TLS memory reference:
+       //
+       //         MOVQ 8(TLS), CX // load m into CX
+       //
+       // The 2-instruction and 1-instruction forms correspond roughly to
+       // ELF TLS initial exec mode and ELF TLS local exec mode, respectively.
+       //
+       // We applies this rewrite on systems that support the 1-instruction form.
+       // The decision is made using only the operating system (and probably
+       // the -shared flag, eventually), not the link mode. If some link modes
+       // on a particular operating system require the 2-instruction form,
+       // then all builds for that operating system will use the 2-instruction
+       // form, so that the link mode decision can be delayed to link time.
+       //
+       // In this way, all supported systems use identical instructions to
+       // access TLS, and they are rewritten appropriately first here in
+       // liblink and then finally using relocations in the linker.
+
+       if canuselocaltls(ctxt) != 0 {
+
+               // Reduce TLS initial exec model to TLS local exec model.
+               // Sequences like
+               //      MOVQ TLS, BX
+               //      ... off(BX)(TLS*1) ...
+               // become
+               //      NOP
+               //      ... off(TLS) ...
+               //
+               // TODO(rsc): Remove the Hsolaris special case. It exists only to
+               // guarantee we are producing byte-identical binaries as before this code.
+               // But it should be unnecessary.
+               if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == D_TLS && D_AX <= p.To.Type && p.To.Type <= D_R15 && ctxt.Headtype != obj.Hsolaris {
+
+                       nopout(p)
+               }
+               if p.From.Index == D_TLS && D_INDIR+D_AX <= p.From.Type && p.From.Type <= D_INDIR+D_R15 {
+                       p.From.Type = D_INDIR + D_TLS
+                       p.From.Scale = 0
+                       p.From.Index = D_NONE
+               }
+
+               if p.To.Index == D_TLS && D_INDIR+D_AX <= p.To.Type && p.To.Type <= D_INDIR+D_R15 {
+                       p.To.Type = D_INDIR + D_TLS
+                       p.To.Scale = 0
+                       p.To.Index = D_NONE
+               }
+       } else {
+
+               // As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
+               // The instruction
+               //      MOVQ off(TLS), BX
+               // becomes the sequence
+               //      MOVQ TLS, BX
+               //      MOVQ off(BX)(TLS*1), BX
+               // This allows the C compilers to emit references to m and g using the direct off(TLS) form.
+               if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == D_INDIR+D_TLS && D_AX <= p.To.Type && p.To.Type <= D_R15 {
+
+                       q = obj.Appendp(ctxt, p)
+                       q.As = p.As
+                       q.From = p.From
+                       q.From.Type = D_INDIR + p.To.Type
+                       q.From.Index = D_TLS
+                       q.From.Scale = 2 // TODO: use 1
+                       q.To = p.To
+                       p.From.Type = D_TLS
+                       p.From.Index = D_NONE
+                       p.From.Offset = 0
+               }
+       }
+
+       // TODO: Remove.
+       if ctxt.Headtype == obj.Hwindows || ctxt.Headtype == obj.Hplan9 {
+
+               if p.From.Scale == 1 && p.From.Index == D_TLS {
+                       p.From.Scale = 2
+               }
+               if p.To.Scale == 1 && p.To.Index == D_TLS {
+                       p.To.Scale = 2
+               }
+       }
+
+       if ctxt.Headtype == obj.Hnacl {
+               nacladdr(ctxt, p, &p.From)
+               nacladdr(ctxt, p, &p.To)
+       }
+
+       // Maintain information about code generation mode.
+       if ctxt.Mode == 0 {
+
+               ctxt.Mode = 64
+       }
+       p.Mode = int8(ctxt.Mode)
+
+       switch p.As {
+       case AMODE:
+               if p.From.Type == D_CONST || p.From.Type == D_INDIR+D_NONE {
+                       switch int(p.From.Offset) {
+                       case 16,
+                               32,
+                               64:
+                               ctxt.Mode = int(p.From.Offset)
+                               break
+                       }
+               }
+
+               nopout(p)
+               break
+       }
+
+       // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+       switch p.As {
+
+       case ACALL,
+               AJMP,
+               ARET:
+               if (p.To.Type == D_EXTERN || p.To.Type == D_STATIC) && p.To.Sym != nil {
+                       p.To.Type = D_BRANCH
+               }
+               break
+       }
+
+       // Rewrite float constants to values stored in memory.
+       switch p.As {
+
+       // Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
+       case AMOVSS:
+               if p.From.Type == D_FCONST {
+
+                       if p.From.U.Dval == 0 {
+                               if p.To.Type >= D_X0 {
+                                       if p.To.Type <= D_X15 {
+                                               p.As = AXORPS
+                                               p.From.Type = p.To.Type
+                                               p.From.Index = p.To.Index
+                                               break
+                                       }
+                               }
+                       }
+               }
+               fallthrough
+
+               // fallthrough
+
+       case AFMOVF,
+               AFADDF,
+               AFSUBF,
+               AFSUBRF,
+               AFMULF,
+               AFDIVF,
+               AFDIVRF,
+               AFCOMF,
+               AFCOMFP,
+               AADDSS,
+               ASUBSS,
+               AMULSS,
+               ADIVSS,
+               ACOMISS,
+               AUCOMISS:
+               if p.From.Type == D_FCONST {
+
+                       var i32 uint32
+                       var f32 float32
+                       f32 = float32(p.From.U.Dval)
+                       i32 = math.Float32bits(f32)
+                       literal = fmt.Sprintf("$f32.%08x", i32)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint32(ctxt, s, i32)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_EXTERN
+                       p.From.Sym = s
+                       p.From.Offset = 0
+               }
+
+               // Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
+       case AMOVSD:
+               if p.From.Type == D_FCONST {
+
+                       if p.From.U.Dval == 0 {
+                               if p.To.Type >= D_X0 {
+                                       if p.To.Type <= D_X15 {
+                                               p.As = AXORPS
+                                               p.From.Type = p.To.Type
+                                               p.From.Index = p.To.Index
+                                               break
+                                       }
+                               }
+                       }
+               }
+               fallthrough
+
+               // fallthrough
+       case AFMOVD,
+               AFADDD,
+               AFSUBD,
+               AFSUBRD,
+               AFMULD,
+               AFDIVD,
+               AFDIVRD,
+               AFCOMD,
+               AFCOMDP,
+               AADDSD,
+               ASUBSD,
+               AMULSD,
+               ADIVSD,
+               ACOMISD,
+               AUCOMISD:
+               if p.From.Type == D_FCONST {
+
+                       var i64 uint64
+                       i64 = math.Float64bits(p.From.U.Dval)
+                       literal = fmt.Sprintf("$f64.%016x", i64)
+                       s = obj.Linklookup(ctxt, literal, 0)
+                       if s.Type == 0 {
+                               s.Type = obj.SRODATA
+                               obj.Adduint64(ctxt, s, i64)
+                               s.Reachable = 0
+                       }
+
+                       p.From.Type = D_EXTERN
+                       p.From.Sym = s
+                       p.From.Offset = 0
+               }
+
+               break
+       }
+}
+
+func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+       if p.As == ALEAL || p.As == ALEAQ {
+               return
+       }
+
+       if a.Type == D_BP || a.Type == D_INDIR+D_BP {
+               ctxt.Diag("invalid address: %v", p)
+               return
+       }
+
+       if a.Type == D_INDIR+D_TLS {
+               a.Type = D_INDIR + D_BP
+       } else if a.Type == D_TLS {
+               a.Type = D_BP
+       }
+       if D_INDIR <= a.Type && a.Type <= D_INDIR+D_INDIR {
+               switch a.Type {
+               // all ok
+               case D_INDIR + D_BP,
+                       D_INDIR + D_SP,
+                       D_INDIR + D_R15:
+                       break
+
+               default:
+                       if a.Index != D_NONE {
+                               ctxt.Diag("invalid address %v", p)
+                       }
+                       a.Index = uint8(a.Type - D_INDIR)
+                       if a.Index != D_NONE {
+                               a.Scale = 1
+                       }
+                       a.Type = D_INDIR + D_R15
+                       break
+               }
+       }
+}
+
+func parsetextconst(arg int64, textstksiz *int64, textarg *int64) {
+       *textstksiz = arg & 0xffffffff
+       if *textstksiz&0x80000000 != 0 {
+               *textstksiz = -(-*textstksiz & 0xffffffff)
+       }
+
+       *textarg = (arg >> 32) & 0xffffffff
+       if *textarg&0x80000000 != 0 {
+               *textarg = 0
+       }
+       *textarg = (*textarg + 7) &^ 7
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+       var p *obj.Prog
+       var q *obj.Prog
+       var p1 *obj.Prog
+       var p2 *obj.Prog
+       var autoffset int32
+       var deltasp int32
+       var a int
+       var pcsize int
+       var textstksiz int64
+       var textarg int64
+
+       if ctxt.Tlsg == nil {
+               ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+       }
+       if ctxt.Symmorestack[0] == nil {
+               ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+               ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+       }
+
+       if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
+               ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+       }
+
+       ctxt.Cursym = cursym
+
+       if cursym.Text == nil || cursym.Text.Link == nil {
+               return
+       }
+
+       p = cursym.Text
+       parsetextconst(p.To.Offset, &textstksiz, &textarg)
+       autoffset = int32(textstksiz)
+       if autoffset < 0 {
+               autoffset = 0
+       }
+
+       cursym.Args = int32(p.To.Offset >> 32)
+       cursym.Locals = int32(textstksiz)
+
+       if autoffset < obj.StackSmall && !(p.From.Scale&obj.NOSPLIT != 0) {
+               for q = p; q != nil; q = q.Link {
+                       if q.As == ACALL {
+                               goto noleaf
+                       }
+                       if (q.As == ADUFFCOPY || q.As == ADUFFZERO) && autoffset >= obj.StackSmall-8 {
+                               goto noleaf
+                       }
+               }
+
+               p.From.Scale |= obj.NOSPLIT
+       noleaf:
+       }
+
+       q = nil
+       if !(p.From.Scale&obj.NOSPLIT != 0) || (p.From.Scale&obj.WRAPPER != 0) {
+               p = obj.Appendp(ctxt, p)
+               p = load_g_cx(ctxt, p) // load g into CX
+       }
+
+       if !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+               p = stacksplit(ctxt, p, autoffset, int32(textarg), bool2int(!(cursym.Text.From.Scale&obj.NEEDCTXT != 0)), &q) // emit split check
+       }
+
+       if autoffset != 0 {
+
+               if autoffset%int32(ctxt.Arch.Regsize) != 0 {
+                       ctxt.Diag("unaligned stack size %d", autoffset)
+               }
+               p = obj.Appendp(ctxt, p)
+               p.As = AADJSP
+               p.From.Type = D_CONST
+               p.From.Offset = int64(autoffset)
+               p.Spadj = autoffset
+       } else {
+
+               // zero-byte stack adjustment.
+               // Insert a fake non-zero adjustment so that stkcheck can
+               // recognize the end of the stack-splitting prolog.
+               p = obj.Appendp(ctxt, p)
+
+               p.As = ANOP
+               p.Spadj = int32(-ctxt.Arch.Ptrsize)
+               p = obj.Appendp(ctxt, p)
+               p.As = ANOP
+               p.Spadj = int32(ctxt.Arch.Ptrsize)
+       }
+
+       if q != nil {
+               q.Pcond = p
+       }
+       deltasp = autoffset
+
+       if cursym.Text.From.Scale&obj.WRAPPER != 0 {
+               // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+               //
+               //      MOVQ g_panic(CX), BX
+               //      TESTQ BX, BX
+               //      JEQ end
+               //      LEAQ (autoffset+8)(SP), DI
+               //      CMPQ panic_argp(BX), DI
+               //      JNE end
+               //      MOVQ SP, panic_argp(BX)
+               // end:
+               //      NOP
+               //
+               // The NOP is needed to give the jumps somewhere to land.
+               // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
+
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVQ
+               p.From.Type = D_INDIR + D_CX
+               p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+               p.To.Type = D_BX
+               if ctxt.Headtype == obj.Hnacl {
+                       p.As = AMOVL
+                       p.From.Type = D_INDIR + D_R15
+                       p.From.Scale = 1
+                       p.From.Index = D_CX
+               }
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ATESTQ
+               p.From.Type = D_BX
+               p.To.Type = D_BX
+               if ctxt.Headtype == obj.Hnacl {
+                       p.As = ATESTL
+               }
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJEQ
+               p.To.Type = D_BRANCH
+               p1 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ALEAQ
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = int64(autoffset) + 8
+               p.To.Type = D_DI
+               if ctxt.Headtype == obj.Hnacl {
+                       p.As = ALEAL
+               }
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ACMPQ
+               p.From.Type = D_INDIR + D_BX
+               p.From.Offset = 0 // Panic.argp
+               p.To.Type = D_DI
+               if ctxt.Headtype == obj.Hnacl {
+                       p.As = ACMPL
+                       p.From.Type = D_INDIR + D_R15
+                       p.From.Scale = 1
+                       p.From.Index = D_BX
+               }
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJNE
+               p.To.Type = D_BRANCH
+               p2 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVQ
+               p.From.Type = D_SP
+               p.To.Type = D_INDIR + D_BX
+               p.To.Offset = 0 // Panic.argp
+               if ctxt.Headtype == obj.Hnacl {
+                       p.As = AMOVL
+                       p.To.Type = D_INDIR + D_R15
+                       p.To.Scale = 1
+                       p.To.Index = D_BX
+               }
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ANOP
+               p1.Pcond = p
+               p2.Pcond = p
+       }
+
+       if ctxt.Debugzerostack != 0 && autoffset != 0 && !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+               // 6l -Z means zero the stack frame on entry.
+               // This slows down function calls but can help avoid
+               // false positives in garbage collection.
+               p = obj.Appendp(ctxt, p)
+
+               p.As = AMOVQ
+               p.From.Type = D_SP
+               p.To.Type = D_DI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVQ
+               p.From.Type = D_CONST
+               p.From.Offset = int64(autoffset) / 8
+               p.To.Type = D_CX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AMOVQ
+               p.From.Type = D_CONST
+               p.From.Offset = 0
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AREP
+
+               p = obj.Appendp(ctxt, p)
+               p.As = ASTOSQ
+       }
+
+       for ; p != nil; p = p.Link {
+               pcsize = int(p.Mode) / 8
+               a = int(p.From.Type)
+               if a == D_AUTO {
+                       p.From.Offset += int64(deltasp)
+               }
+               if a == D_PARAM {
+                       p.From.Offset += int64(deltasp) + int64(pcsize)
+               }
+               a = int(p.To.Type)
+               if a == D_AUTO {
+                       p.To.Offset += int64(deltasp)
+               }
+               if a == D_PARAM {
+                       p.To.Offset += int64(deltasp) + int64(pcsize)
+               }
+
+               switch p.As {
+               default:
+                       continue
+
+               case APUSHL,
+                       APUSHFL:
+                       deltasp += 4
+                       p.Spadj = 4
+                       continue
+
+               case APUSHQ,
+                       APUSHFQ:
+                       deltasp += 8
+                       p.Spadj = 8
+                       continue
+
+               case APUSHW,
+                       APUSHFW:
+                       deltasp += 2
+                       p.Spadj = 2
+                       continue
+
+               case APOPL,
+                       APOPFL:
+                       deltasp -= 4
+                       p.Spadj = -4
+                       continue
+
+               case APOPQ,
+                       APOPFQ:
+                       deltasp -= 8
+                       p.Spadj = -8
+                       continue
+
+               case APOPW,
+                       APOPFW:
+                       deltasp -= 2
+                       p.Spadj = -2
+                       continue
+
+               case ARET:
+                       break
+               }
+
+               if autoffset != deltasp {
+                       ctxt.Diag("unbalanced PUSH/POP")
+               }
+
+               if autoffset != 0 {
+                       p.As = AADJSP
+                       p.From.Type = D_CONST
+                       p.From.Offset = int64(-autoffset)
+                       p.Spadj = -autoffset
+                       p = obj.Appendp(ctxt, p)
+                       p.As = ARET
+
+                       // If there are instructions following
+                       // this ARET, they come from a branch
+                       // with the same stackframe, so undo
+                       // the cleanup.
+                       p.Spadj = +autoffset
+               }
+
+               if p.To.Sym != nil { // retjmp
+                       p.As = AJMP
+               }
+       }
+}
+
+func indir_cx(ctxt *obj.Link, a *obj.Addr) {
+       if ctxt.Headtype == obj.Hnacl {
+               a.Type = D_INDIR + D_R15
+               a.Index = D_CX
+               a.Scale = 1
+               return
+       }
+
+       a.Type = D_INDIR + D_CX
+}
+
+// Append code to p to load g into cx.
+// Overwrites p with the first instruction (no first appendp).
+// Overwriting p is unusual but it lets use this in both the
+// prologue (caller must call appendp first) and in the epilogue.
+// Returns last new instruction.
+func load_g_cx(ctxt *obj.Link, p *obj.Prog) *obj.Prog {
+
+       var next *obj.Prog
+
+       p.As = AMOVQ
+       if ctxt.Arch.Ptrsize == 4 {
+               p.As = AMOVL
+       }
+       p.From.Type = D_INDIR + D_TLS
+       p.From.Offset = 0
+       p.To.Type = D_CX
+
+       next = p.Link
+       progedit(ctxt, p)
+       for p.Link != next {
+               p = p.Link
+       }
+
+       if p.From.Index == D_TLS {
+               p.From.Scale = 2
+       }
+
+       return p
+}
+
+// Append code to p to check for stack split.
+// Appends to (does not overwrite) p.
+// Assumes g is in CX.
+// Returns last new instruction.
+// On return, *jmpok is the instruction that should jump
+// to the stack frame allocation if no split is needed.
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32, noctxt int, jmpok **obj.Prog) *obj.Prog {
+
+       var q *obj.Prog
+       var q1 *obj.Prog
+       var cmp int
+       var lea int
+       var mov int
+       var sub int
+
+       cmp = ACMPQ
+       lea = ALEAQ
+       mov = AMOVQ
+       sub = ASUBQ
+
+       if ctxt.Headtype == obj.Hnacl {
+               cmp = ACMPL
+               lea = ALEAL
+               mov = AMOVL
+               sub = ASUBL
+       }
+
+       q1 = nil
+       if framesize <= obj.StackSmall {
+               // small stack: SP <= stackguard
+               //      CMPQ SP, stackguard
+               p = obj.Appendp(ctxt, p)
+
+               p.As = int16(cmp)
+               p.From.Type = D_SP
+               indir_cx(ctxt, &p.To)
+               p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+       } else if framesize <= obj.StackBig {
+               // large stack: SP-framesize <= stackguard-StackSmall
+               //      LEAQ -xxx(SP), AX
+               //      CMPQ AX, stackguard
+               p = obj.Appendp(ctxt, p)
+
+               p.As = int16(lea)
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = -(int64(framesize) - obj.StackSmall)
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = int16(cmp)
+               p.From.Type = D_AX
+               indir_cx(ctxt, &p.To)
+               p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+       } 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.
+               //      MOVQ    stackguard, CX
+               //      CMPQ    CX, $StackPreempt
+               //      JEQ     label-of-call-to-morestack
+               //      LEAQ    StackGuard(SP), AX
+               //      SUBQ    CX, AX
+               //      CMPQ    AX, $(framesize+(StackGuard-StackSmall))
+
+               p = obj.Appendp(ctxt, p)
+
+               p.As = int16(mov)
+               indir_cx(ctxt, &p.From)
+               p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+               if ctxt.Cursym.Cfunc != 0 {
+                       p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+               }
+               p.To.Type = D_SI
+
+               p = obj.Appendp(ctxt, p)
+               p.As = int16(cmp)
+               p.From.Type = D_SI
+               p.To.Type = D_CONST
+               p.To.Offset = obj.StackPreempt
+
+               p = obj.Appendp(ctxt, p)
+               p.As = AJEQ
+               p.To.Type = D_BRANCH
+               q1 = p
+
+               p = obj.Appendp(ctxt, p)
+               p.As = int16(lea)
+               p.From.Type = D_INDIR + D_SP
+               p.From.Offset = obj.StackGuard
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = int16(sub)
+               p.From.Type = D_SI
+               p.To.Type = D_AX
+
+               p = obj.Appendp(ctxt, p)
+               p.As = int16(cmp)
+               p.From.Type = D_AX
+               p.To.Type = D_CONST
+               p.To.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+       }
+
+       // common
+       p = obj.Appendp(ctxt, p)
+
+       p.As = AJHI
+       p.To.Type = D_BRANCH
+       q = p
+
+       p = obj.Appendp(ctxt, p)
+       p.As = ACALL
+       p.To.Type = D_BRANCH
+       if ctxt.Cursym.Cfunc != 0 {
+               p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+       } else {
+
+               p.To.Sym = ctxt.Symmorestack[noctxt]
+       }
+
+       p = obj.Appendp(ctxt, p)
+       p.As = AJMP
+       p.To.Type = D_BRANCH
+       p.Pcond = ctxt.Cursym.Text.Link
+
+       if q != nil {
+               q.Pcond = p.Link
+       }
+       if q1 != nil {
+               q1.Pcond = q.Link
+       }
+
+       *jmpok = q
+       return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+       var firstp *obj.Prog
+       var lastp *obj.Prog
+
+       ctxt.Cursym = s
+
+       firstp = ctxt.NewProg()
+       lastp = firstp
+       xfol(ctxt, s.Text, &lastp)
+       lastp.Link = nil
+       s.Text = firstp.Link
+}
+
+func nofollow(a int) int {
+       switch a {
+       case AJMP,
+               ARET,
+               AIRETL,
+               AIRETQ,
+               AIRETW,
+               ARETFL,
+               ARETFQ,
+               ARETFW,
+               AUNDEF:
+               return 1
+       }
+
+       return 0
+}
+
+func pushpop(a int) int {
+       switch a {
+       case APUSHL,
+               APUSHFL,
+               APUSHQ,
+               APUSHFQ,
+               APUSHW,
+               APUSHFW,
+               APOPL,
+               APOPFL,
+               APOPQ,
+               APOPFQ,
+               APOPW,
+               APOPFW:
+               return 1
+       }
+
+       return 0
+}
+
+func relinv(a int) int {
+       switch a {
+       case AJEQ:
+               return AJNE
+       case AJNE:
+               return AJEQ
+       case AJLE:
+               return AJGT
+       case AJLS:
+               return AJHI
+       case AJLT:
+               return AJGE
+       case AJMI:
+               return AJPL
+       case AJGE:
+               return AJLT
+       case AJPL:
+               return AJMI
+       case AJGT:
+               return AJLE
+       case AJHI:
+               return AJLS
+       case AJCS:
+               return AJCC
+       case AJCC:
+               return AJCS
+       case AJPS:
+               return AJPC
+       case AJPC:
+               return AJPS
+       case AJOS:
+               return AJOC
+       case AJOC:
+               return AJOS
+       }
+
+       log.Fatalf("unknown relation: %s", Anames[a])
+       return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+       var q *obj.Prog
+       var i int
+       var a int
+
+loop:
+       if p == nil {
+               return
+       }
+       if p.As == AJMP {
+               q = p.Pcond
+               if q != nil && q.As != ATEXT {
+                       /* mark instruction as done and continue layout at target of jump */
+                       p.Mark = 1
+
+                       p = q
+                       if p.Mark == 0 {
+                               goto loop
+                       }
+               }
+       }
+
+       if p.Mark != 0 {
+               /*
+                * p goes here, but already used it elsewhere.
+                * copy up to 4 instructions or else branch to other copy.
+                */
+               i = 0
+               q = p
+               for ; i < 4; (func() { i++; q = q.Link })() {
+
+                       if q == nil {
+                               break
+                       }
+                       if q == *last {
+                               break
+                       }
+                       a = int(q.As)
+                       if a == ANOP {
+                               i--
+                               continue
+                       }
+
+                       if nofollow(a) != 0 || pushpop(a) != 0 {
+                               break // NOTE(rsc): arm does goto copy
+                       }
+                       if q.Pcond == nil || q.Pcond.Mark != 0 {
+                               continue
+                       }
+                       if a == ACALL || a == ALOOP {
+                               continue
+                       }
+                       for {
+                               if p.As == ANOP {
+                                       p = p.Link
+                                       continue
+                               }
+
+                               q = obj.Copyp(ctxt, p)
+                               p = p.Link
+                               q.Mark = 1
+                               (*last).Link = q
+                               *last = q
+                               if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+                                       continue
+                               }
+
+                               q.As = int16(relinv(int(q.As)))
+                               p = q.Pcond
+                               q.Pcond = q.Link
+                               q.Link = p
+                               xfol(ctxt, q.Link, last)
+                               p = q.Link
+                               if p.Mark != 0 {
+                                       return
+                               }
+                               goto loop
+                               /* */
+                       }
+               }
+               q = ctxt.NewProg()
+               q.As = AJMP
+               q.Lineno = p.Lineno
+               q.To.Type = D_BRANCH
+               q.To.Offset = p.Pc
+               q.Pcond = p
+               p = q
+       }
+
+       /* emit p */
+       p.Mark = 1
+
+       (*last).Link = p
+       *last = p
+       a = int(p.As)
+
+       /* continue loop with what comes after p */
+       if nofollow(a) != 0 {
+
+               return
+       }
+       if p.Pcond != nil && a != ACALL {
+               /*
+                * some kind of conditional branch.
+                * recurse to follow one path.
+                * continue loop on the other.
+                */
+               q = obj.Brchain(ctxt, p.Pcond)
+               if q != nil {
+
+                       p.Pcond = q
+               }
+               q = obj.Brchain(ctxt, p.Link)
+               if q != nil {
+                       p.Link = q
+               }
+               if p.From.Type == D_CONST {
+                       if p.From.Offset == 1 {
+                               /*
+                                * expect conditional jump to be taken.
+                                * rewrite so that's the fall-through case.
+                                */
+                               p.As = int16(relinv(a))
+
+                               q = p.Link
+                               p.Link = p.Pcond
+                               p.Pcond = q
+                       }
+               } else {
+
+                       q = p.Link
+                       if q.Mark != 0 {
+                               if a != ALOOP {
+                                       p.As = int16(relinv(a))
+                                       p.Link = p.Pcond
+                                       p.Pcond = q
+                               }
+                       }
+               }
+
+               xfol(ctxt, p.Link, last)
+               if p.Pcond.Mark != 0 {
+                       return
+               }
+               p = p.Pcond
+               goto loop
+       }
+
+       p = p.Link
+       goto loop
+}
+
+func prg() *obj.Prog {
+       p := zprg
+       return &p
+}
+
+var Linkamd64 = obj.LinkArch{
+       ByteOrder:     binary.LittleEndian,
+       Pconv:         Pconv,
+       Name:          "amd64",
+       Thechar:       '6',
+       Endian:        obj.LittleEndian,
+       Addstacksplit: addstacksplit,
+       Assemble:      span6,
+       Datasize:      datasize,
+       Follow:        follow,
+       Iscall:        iscall,
+       Isdata:        isdata,
+       Prg:           prg,
+       Progedit:      progedit,
+       Settextflag:   settextflag,
+       Symtype:       symtype,
+       Textflag:      textflag,
+       Minlc:         1,
+       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:         ACALL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          AJMP,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARET,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
+
+var Linkamd64p32 = obj.LinkArch{
+       ByteOrder:     binary.LittleEndian,
+       Pconv:         Pconv,
+       Name:          "amd64p32",
+       Thechar:       '6',
+       Endian:        obj.LittleEndian,
+       Addstacksplit: addstacksplit,
+       Assemble:      span6,
+       Datasize:      datasize,
+       Follow:        follow,
+       Iscall:        iscall,
+       Isdata:        isdata,
+       Prg:           prg,
+       Progedit:      progedit,
+       Settextflag:   settextflag,
+       Symtype:       symtype,
+       Textflag:      textflag,
+       Minlc:         1,
+       Ptrsize:       4,
+       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:         ACALL,
+       ADATA:         ADATA,
+       AEND:          AEND,
+       AFUNCDATA:     AFUNCDATA,
+       AGLOBL:        AGLOBL,
+       AJMP:          AJMP,
+       ANOP:          ANOP,
+       APCDATA:       APCDATA,
+       ARET:          ARET,
+       ATEXT:         ATEXT,
+       ATYPE:         ATYPE,
+       AUSEFIELD:     AUSEFIELD,
+}
diff --git a/src/cmd/internal/obj/x86/util.go b/src/cmd/internal/obj/x86/util.go
new file mode 100644 (file)
index 0000000..4736fab
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x86
+
+const (
+       fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+       if b {
+               return 1
+       }
+       return 0
+}
diff --git a/src/cmd/new5a/a.y b/src/cmd/new5a/a.y
new file mode 100644 (file)
index 0000000..03ea6bf
--- /dev/null
@@ -0,0 +1,755 @@
+// Inferno utils/5a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/5a/a.y
+//
+//     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.
+
+%{
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/arm"
+)
+%}
+
+%union {
+       sym *asm.Sym
+       lval int32
+       dval float64
+       sval string
+       addr obj.Addr
+}
+
+%left  '|'
+%left  '^'
+%left  '&'
+%left  '<' '>'
+%left  '+' '-'
+%left  '*' '/' '%'
+%token <lval>  LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
+%token <lval>  LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
+%token <lval>  LTYPEB LTYPEC LTYPED LTYPEE
+%token <lval>  LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
+%token <lval>  LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
+%token <lval>  LCONST LSP LSB LFP LPC
+%token <lval>  LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
+%token <lval>  LCOND LS LAT
+%token <dval>  LFCONST
+%token <sval>  LSCONST
+%token <sym>   LNAME LLAB LVAR
+%type  <lval>  con expr oexpr pointer offset sreg spreg creg
+%type  <lval>  rcon cond reglist
+%type  <addr>  gen rel reg regreg freg shift fcon frcon
+%type  <addr>  imm ximm name oreg ireg nireg ioreg imsr
+%%
+prog:
+|      prog
+       {
+               stmtline = asm.Lineno;
+       }
+       line
+
+line:
+       LNAME ':'
+       {
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
+       }
+       line
+|      LNAME '=' expr ';'
+       {
+               $1.Type = LVAR;
+               $1.Value = int64($3);
+       }
+|      LVAR '=' expr ';'
+       {
+               if $1.Value != int64($3) {
+                       yyerror("redeclaration of %s", $1.Name)
+               }
+               $1.Value = int64($3);
+       }
+|      ';'
+|      inst ';'
+|      error ';'
+
+inst:
+/*
+ * ADD
+ */
+       LTYPE1 cond imsr ',' spreg ',' reg
+       {
+               outcode($1, $2, &$3, $5, &$7);
+       }
+|      LTYPE1 cond imsr ',' spreg ','
+       {
+               outcode($1, $2, &$3, $5, &nullgen);
+       }
+|      LTYPE1 cond imsr ',' reg
+       {
+               outcode($1, $2, &$3, NREG, &$5);
+       }
+/*
+ * MVN
+ */
+|      LTYPE2 cond imsr ',' reg
+       {
+               outcode($1, $2, &$3, NREG, &$5);
+       }
+/*
+ * MOVW
+ */
+|      LTYPE3 cond gen ',' gen
+       {
+               outcode($1, $2, &$3, NREG, &$5);
+       }
+/*
+ * B/BL
+ */
+|      LTYPE4 cond comma rel
+       {
+               outcode($1, $2, &nullgen, NREG, &$4);
+       }
+|      LTYPE4 cond comma nireg
+       {
+               outcode($1, $2, &nullgen, NREG, &$4);
+       }
+/*
+ * BX
+ */
+|      LTYPEBX comma ireg
+       {
+               outcode($1, Always, &nullgen, NREG, &$3);
+       }
+/*
+ * BEQ
+ */
+|      LTYPE5 comma rel
+       {
+               outcode($1, Always, &nullgen, NREG, &$3);
+       }
+/*
+ * SWI
+ */
+|      LTYPE6 cond comma gen
+       {
+               outcode($1, $2, &nullgen, NREG, &$4);
+       }
+/*
+ * CMP
+ */
+|      LTYPE7 cond imsr ',' spreg comma
+       {
+               outcode($1, $2, &$3, $5, &nullgen);
+       }
+/*
+ * MOVM
+ */
+|      LTYPE8 cond ioreg ',' '[' reglist ']'
+       {
+               var g obj.Addr
+
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = int64($6);
+               outcode($1, $2, &$3, NREG, &g);
+       }
+|      LTYPE8 cond '[' reglist ']' ',' ioreg
+       {
+               var g obj.Addr
+
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = int64($4);
+               outcode($1, $2, &g, NREG, &$7);
+       }
+/*
+ * SWAP
+ */
+|      LTYPE9 cond reg ',' ireg ',' reg
+       {
+               outcode($1, $2, &$5, int32($3.Reg), &$7);
+       }
+|      LTYPE9 cond reg ',' ireg comma
+       {
+               outcode($1, $2, &$5, int32($3.Reg), &$3);
+       }
+|      LTYPE9 cond comma ireg ',' reg
+       {
+               outcode($1, $2, &$4, int32($6.Reg), &$6);
+       }
+/*
+ * RET
+ */
+|      LTYPEA cond comma
+       {
+               outcode($1, $2, &nullgen, NREG, &nullgen);
+       }
+/*
+ * TEXT/GLOBL
+ */
+|      LTYPEB name ',' imm
+       {
+               asm.Settext($2.Sym);
+               $4.Type = D_CONST2;
+               $4.Offset2 = -obj.ArgsSizeUnknown;
+               outcode($1, Always, &$2, 0, &$4);
+       }
+|      LTYPEB name ',' con ',' imm
+       {
+               asm.Settext($2.Sym);
+               $6.Type = D_CONST2;
+               $6.Offset2 = -obj.ArgsSizeUnknown;
+               outcode($1, Always, &$2, $4, &$6);
+       }
+|      LTYPEB name ',' con ',' imm '-' con
+       {
+               asm.Settext($2.Sym);
+               $6.Type = D_CONST2;
+               $6.Offset2 = $8;
+               outcode($1, Always, &$2, $4, &$6);
+       }
+/*
+ * DATA
+ */
+|      LTYPEC name '/' con ',' ximm
+       {
+               outcode($1, Always, &$2, $4, &$6);
+       }
+/*
+ * CASE
+ */
+|      LTYPED cond reg comma
+       {
+               outcode($1, $2, &$3, NREG, &nullgen);
+       }
+/*
+ * word
+ */
+|      LTYPEH comma ximm
+       {
+               outcode($1, Always, &nullgen, NREG, &$3);
+       }
+/*
+ * floating-point coprocessor
+ */
+|      LTYPEI cond freg ',' freg
+       {
+               outcode($1, $2, &$3, NREG, &$5);
+       }
+|      LTYPEK cond frcon ',' freg
+       {
+               outcode($1, $2, &$3, NREG, &$5);
+       }
+|      LTYPEK cond frcon ',' LFREG ',' freg
+       {
+               outcode($1, $2, &$3, $5, &$7);
+       }
+|      LTYPEL cond freg ',' freg comma
+       {
+               outcode($1, $2, &$3, int32($5.Reg), &nullgen);
+       }
+/*
+ * MCR MRC
+ */
+|      LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
+       {
+               var g obj.Addr
+
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = int64(
+                       (0xe << 24) |           /* opcode */
+                       ($1 << 20) |            /* MCR/MRC */
+                       ($2 << 28) |            /* scond */
+                       (($3 & 15) << 8) |      /* coprocessor number */
+                       (($5 & 7) << 21) |      /* coprocessor operation */
+                       (($7 & 15) << 12) |     /* arm register */
+                       (($9 & 15) << 16) |     /* Crn */
+                       (($11 & 15) << 0) |     /* Crm */
+                       (($12 & 7) << 5) |      /* coprocessor information */
+                       (1<<4));                        /* must be set */
+               outcode(AMRC, Always, &nullgen, NREG, &g);
+       }
+/*
+ * MULL r1,r2,(hi,lo)
+ */
+|      LTYPEM cond reg ',' reg ',' regreg
+       {
+               outcode($1, $2, &$3, int32($5.Reg), &$7);
+       }
+/*
+ * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
+ * MULAW{T,B} r1,r2,r3,r4
+ */
+|      LTYPEN cond reg ',' reg ',' reg ',' spreg
+       {
+               $7.Type = D_REGREG2;
+               $7.Offset = int64($9);
+               outcode($1, $2, &$3, int32($5.Reg), &$7);
+       }
+/*
+ * PLD
+ */
+|      LTYPEPLD oreg
+       {
+               outcode($1, Always, &$2, NREG, &nullgen);
+       }
+/*
+ * PCDATA
+ */
+|      LTYPEPC gen ',' gen
+       {
+               if $2.Type != D_CONST || $4.Type != D_CONST {
+                       yyerror("arguments to PCDATA must be integer constants")
+               }
+               outcode($1, Always, &$2, NREG, &$4);
+       }
+/*
+ * FUNCDATA
+ */
+|      LTYPEF gen ',' gen
+       {
+               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, Always, &$2, NREG, &$4);
+       }
+/*
+ * END
+ */
+|      LTYPEE comma
+       {
+               outcode($1, Always, &nullgen, NREG, &nullgen);
+       }
+
+cond:
+       {
+               $$ = Always;
+       }
+|      cond LCOND
+       {
+               $$ = ($1 & ^ C_SCOND) | $2;
+       }
+|      cond LS
+       {
+               $$ = $1 | $2;
+       }
+
+comma:
+|      ',' comma
+
+rel:
+       con '(' LPC ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_BRANCH;
+               $$.Offset = int64($1) + int64(asm.PC);
+       }
+|      LNAME offset
+       {
+               $1 = asm.LabelLookup($1);
+               $$ = nullgen;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname)
+               }
+               $$.Type = D_BRANCH;
+               $$.Offset = $1.Value + int64($2);
+       }
+
+ximm:  '$' con
+       {
+               $$ = nullgen;
+               $$.Type = D_CONST;
+               $$.Offset = int64($2);
+       }
+|      '$' oreg
+       {
+               $$ = $2;
+               $$.Type = D_CONST;
+       }
+|      '$' '*' '$' oreg
+       {
+               $$ = $4;
+               $$.Type = D_OCONST;
+       }
+|      '$' LSCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_SCONST;
+               $$.U.Sval = $2
+       }
+|      fcon
+
+fcon:
+       '$' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = $2;
+       }
+|      '$' '-' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = -$3;
+       }
+
+reglist:
+       spreg
+       {
+               $$ = 1 << uint($1);
+       }
+|      spreg '-' spreg
+       {
+               $$=0;
+               for i:=$1; i<=$3; i++ {
+                       $$ |= 1<<uint(i)
+               }
+               for i:=$3; i<=$1; i++ {
+                       $$ |= 1<<uint(i)
+               }
+       }
+|      spreg comma reglist
+       {
+               $$ = (1<<uint($1)) | $3;
+       }
+
+gen:
+       reg
+|      ximm
+|      shift
+|      shift '(' spreg ')'
+       {
+               $$ = $1;
+               $$.Reg = int8($3);
+       }
+|      LPSR
+       {
+               $$ = nullgen;
+               $$.Type = D_PSR;
+               $$.Reg = int8($1);
+       }
+|      LFCR
+       {
+               $$ = nullgen;
+               $$.Type = D_FPCR;
+               $$.Reg = int8($1);
+       }
+|      con
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Offset = int64($1);
+       }
+|      oreg
+|      freg
+
+nireg:
+       ireg
+|      name
+       {
+               $$ = $1;
+               if($1.Name != D_EXTERN && $1.Name != D_STATIC) {
+               }
+       }
+
+ireg:
+       '(' spreg ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Reg = int8($2);
+               $$.Offset = 0;
+       }
+
+ioreg:
+       ireg
+|      con '(' sreg ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Reg = int8($3);
+               $$.Offset = int64($1);
+       }
+
+oreg:
+       name
+|      name '(' sreg ')'
+       {
+               $$ = $1;
+               $$.Type = D_OREG;
+               $$.Reg = int8($3);
+       }
+|      ioreg
+
+imsr:
+       reg
+|      imm
+|      shift
+
+imm:   '$' con
+       {
+               $$ = nullgen;
+               $$.Type = D_CONST;
+               $$.Offset = int64($2);
+       }
+
+reg:
+       spreg
+       {
+               $$ = nullgen;
+               $$.Type = D_REG;
+               $$.Reg = int8($1);
+       }
+
+regreg:
+       '(' spreg ',' spreg ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_REGREG;
+               $$.Reg = int8($2);
+               $$.Offset = int64($4);
+       }
+
+shift:
+       spreg '<' '<' rcon
+       {
+               $$ = nullgen;
+               $$.Type = D_SHIFT;
+               $$.Offset = int64($1) | int64($4) | (0 << 5);
+       }
+|      spreg '>' '>' rcon
+       {
+               $$ = nullgen;
+               $$.Type = D_SHIFT;
+               $$.Offset = int64($1) | int64($4) | (1 << 5);
+       }
+|      spreg '-' '>' rcon
+       {
+               $$ = nullgen;
+               $$.Type = D_SHIFT;
+               $$.Offset = int64($1) | int64($4) | (2 << 5);
+       }
+|      spreg LAT '>' rcon
+       {
+               $$ = nullgen;
+               $$.Type = D_SHIFT;
+               $$.Offset = int64($1) | int64($4) | (3 << 5);
+       }
+
+rcon:
+       spreg
+       {
+               if $$ < 0 || $$ >= 16 {
+                       print("register value out of range\n")
+               }
+               $$ = (($1&15) << 8) | (1 << 4);
+       }
+|      con
+       {
+               if $$ < 0 || $$ >= 32 {
+                       print("shift value out of range\n")
+               }
+               $$ = ($1&31) << 7;
+       }
+
+sreg:
+       LREG
+|      LPC
+       {
+               $$ = REGPC;
+       }
+|      LR '(' expr ')'
+       {
+               if $3 < 0 || $3 >= NREG {
+                       print("register value out of range\n")
+               }
+               $$ = $3;
+       }
+
+spreg:
+       sreg
+|      LSP
+       {
+               $$ = REGSP;
+       }
+
+creg:
+       LCREG
+|      LC '(' expr ')'
+       {
+               if $3 < 0 || $3 >= NREG {
+                       print("register value out of range\n")
+               }
+               $$ = $3;
+       }
+
+frcon:
+       freg
+|      fcon
+
+freg:
+       LFREG
+       {
+               $$ = nullgen;
+               $$.Type = D_FREG;
+               $$.Reg = int8($1);
+       }
+|      LF '(' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_FREG;
+               $$.Reg = int8($3);
+       }
+
+name:
+       con '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = int8($3);
+               $$.Sym = nil;
+               $$.Offset = int64($1);
+       }
+|      LNAME offset '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = int8($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = int64($2);
+       }
+|      LNAME '<' '>' offset '(' LSB ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = D_STATIC;
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = int64($4);
+       }
+
+offset:
+       {
+               $$ = 0;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+
+pointer:
+       LSB
+|      LSP
+|      LFP
+
+con:
+       LCONST
+|      LVAR
+       {
+               $$ = int32($1.Value);
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '~' con
+       {
+               $$ = ^$2;
+       }
+|      '(' expr ')'
+       {
+               $$ = $2;
+       }
+
+oexpr:
+       {
+               $$ = 0;
+       }
+|      ',' 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 << uint($4);
+       }
+|      expr '>' '>' expr
+       {
+               $$ = $1 >> uint($4);
+       }
+|      expr '&' expr
+       {
+               $$ = $1 & $3;
+       }
+|      expr '^' expr
+       {
+               $$ = $1 ^ $3;
+       }
+|      expr '|' expr
+       {
+               $$ = $1 | $3;
+       }
diff --git a/src/cmd/new5a/lex.go b/src/cmd/new5a/lex.go
new file mode 100644 (file)
index 0000000..cc7d25e
--- /dev/null
@@ -0,0 +1,372 @@
+// Inferno utils/5a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.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.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/arm"
+)
+
+var (
+       yyerror  = asm.Yyerror
+       nullgen  obj.Addr
+       stmtline int32
+)
+
+const Always = 14
+
+func main() {
+       cinit()
+
+       asm.LSCONST = LSCONST
+       asm.LCONST = LCONST
+       asm.LFCONST = LFCONST
+       asm.LNAME = LNAME
+       asm.LVAR = LVAR
+       asm.LLAB = LLAB
+
+       asm.Lexinit = lexinit
+       asm.Cclean = cclean
+       asm.Yyparse = yyparse
+
+       asm.Thechar = '5'
+       asm.Thestring = "arm"
+       asm.Thelinkarch = &arm.Linkarm
+
+       asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+       var av asm.Yylval
+       tok := asm.Yylex(&av)
+       v.sym = av.Sym
+       v.lval = int32(av.Lval)
+       v.sval = av.Sval
+       v.dval = av.Dval
+       return tok
+}
+
+func (yy) Error(msg string) {
+       asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+       yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+       {"SP", LSP, arm.D_AUTO},
+       {"SB", LSB, arm.D_EXTERN},
+       {"FP", LFP, arm.D_PARAM},
+       {"PC", LPC, arm.D_BRANCH},
+       {"R", LR, 0},
+       {"R0", LREG, 0},
+       {"R1", LREG, 1},
+       {"R2", LREG, 2},
+       {"R3", LREG, 3},
+       {"R4", LREG, 4},
+       {"R5", LREG, 5},
+       {"R6", LREG, 6},
+       {"R7", LREG, 7},
+       {"R8", LREG, 8},
+       {"R9", LREG, 9},
+       {"g", LREG, 10}, // avoid unintentionally clobber g using R10
+       {"R11", LREG, 11},
+       {"R12", LREG, 12},
+       {"R13", LREG, 13},
+       {"R14", LREG, 14},
+       {"R15", LREG, 15},
+       {"F", LF, 0},
+       {"F0", LFREG, 0},
+       {"F1", LFREG, 1},
+       {"F2", LFREG, 2},
+       {"F3", LFREG, 3},
+       {"F4", LFREG, 4},
+       {"F5", LFREG, 5},
+       {"F6", LFREG, 6},
+       {"F7", LFREG, 7},
+       {"F8", LFREG, 8},
+       {"F9", LFREG, 9},
+       {"F10", LFREG, 10},
+       {"F11", LFREG, 11},
+       {"F12", LFREG, 12},
+       {"F13", LFREG, 13},
+       {"F14", LFREG, 14},
+       {"F15", LFREG, 15},
+       {"C", LC, 0},
+       {"C0", LCREG, 0},
+       {"C1", LCREG, 1},
+       {"C2", LCREG, 2},
+       {"C3", LCREG, 3},
+       {"C4", LCREG, 4},
+       {"C5", LCREG, 5},
+       {"C6", LCREG, 6},
+       {"C7", LCREG, 7},
+       {"C8", LCREG, 8},
+       {"C9", LCREG, 9},
+       {"C10", LCREG, 10},
+       {"C11", LCREG, 11},
+       {"C12", LCREG, 12},
+       {"C13", LCREG, 13},
+       {"C14", LCREG, 14},
+       {"C15", LCREG, 15},
+       {"CPSR", LPSR, 0},
+       {"SPSR", LPSR, 1},
+       {"FPSR", LFCR, 0},
+       {"FPCR", LFCR, 1},
+       {".EQ", LCOND, 0},
+       {".NE", LCOND, 1},
+       {".CS", LCOND, 2},
+       {".HS", LCOND, 2},
+       {".CC", LCOND, 3},
+       {".LO", LCOND, 3},
+       {".MI", LCOND, 4},
+       {".PL", LCOND, 5},
+       {".VS", LCOND, 6},
+       {".VC", LCOND, 7},
+       {".HI", LCOND, 8},
+       {".LS", LCOND, 9},
+       {".GE", LCOND, 10},
+       {".LT", LCOND, 11},
+       {".GT", LCOND, 12},
+       {".LE", LCOND, 13},
+       {".AL", LCOND, Always},
+       {".U", LS, arm.C_UBIT},
+       {".S", LS, arm.C_SBIT},
+       {".W", LS, arm.C_WBIT},
+       {".P", LS, arm.C_PBIT},
+       {".PW", LS, arm.C_WBIT | arm.C_PBIT},
+       {".WP", LS, arm.C_WBIT | arm.C_PBIT},
+       {".F", LS, arm.C_FBIT},
+       {".IBW", LS, arm.C_WBIT | arm.C_PBIT | arm.C_UBIT},
+       {".IAW", LS, arm.C_WBIT | arm.C_UBIT},
+       {".DBW", LS, arm.C_WBIT | arm.C_PBIT},
+       {".DAW", LS, arm.C_WBIT},
+       {".IB", LS, arm.C_PBIT | arm.C_UBIT},
+       {".IA", LS, arm.C_UBIT},
+       {".DB", LS, arm.C_PBIT},
+       {".DA", LS, 0},
+       {"@", LAT, 0},
+       {"AND", LTYPE1, arm.AAND},
+       {"EOR", LTYPE1, arm.AEOR},
+       {"SUB", LTYPE1, arm.ASUB},
+       {"RSB", LTYPE1, arm.ARSB},
+       {"ADD", LTYPE1, arm.AADD},
+       {"ADC", LTYPE1, arm.AADC},
+       {"SBC", LTYPE1, arm.ASBC},
+       {"RSC", LTYPE1, arm.ARSC},
+       {"ORR", LTYPE1, arm.AORR},
+       {"BIC", LTYPE1, arm.ABIC},
+       {"SLL", LTYPE1, arm.ASLL},
+       {"SRL", LTYPE1, arm.ASRL},
+       {"SRA", LTYPE1, arm.ASRA},
+       {"MUL", LTYPE1, arm.AMUL},
+       {"MULA", LTYPEN, arm.AMULA},
+       {"DIV", LTYPE1, arm.ADIV},
+       {"MOD", LTYPE1, arm.AMOD},
+       {"MULL", LTYPEM, arm.AMULL},
+       {"MULAL", LTYPEM, arm.AMULAL},
+       {"MULLU", LTYPEM, arm.AMULLU},
+       {"MULALU", LTYPEM, arm.AMULALU},
+       {"MVN", LTYPE2, arm.AMVN}, /* op2 ignored */
+       {"MOVB", LTYPE3, arm.AMOVB},
+       {"MOVBU", LTYPE3, arm.AMOVBU},
+       {"MOVH", LTYPE3, arm.AMOVH},
+       {"MOVHU", LTYPE3, arm.AMOVHU},
+       {"MOVW", LTYPE3, arm.AMOVW},
+       {"MOVD", LTYPE3, arm.AMOVD},
+       {"MOVDF", LTYPE3, arm.AMOVDF},
+       {"MOVDW", LTYPE3, arm.AMOVDW},
+       {"MOVF", LTYPE3, arm.AMOVF},
+       {"MOVFD", LTYPE3, arm.AMOVFD},
+       {"MOVFW", LTYPE3, arm.AMOVFW},
+       {"MOVWD", LTYPE3, arm.AMOVWD},
+       {"MOVWF", LTYPE3, arm.AMOVWF},
+       {"LDREX", LTYPE3, arm.ALDREX},
+       {"LDREXD", LTYPE3, arm.ALDREXD},
+       {"STREX", LTYPE9, arm.ASTREX},
+       {"STREXD", LTYPE9, arm.ASTREXD},
+
+       /*
+               {"NEGF",                LTYPEI, ANEGF},
+               {"NEGD",                LTYPEI, ANEGD},
+               {"SQTF",                LTYPEI, ASQTF},
+               {"SQTD",                LTYPEI, ASQTD},
+               {"RNDF",                LTYPEI, ARNDF},
+               {"RNDD",                LTYPEI, ARNDD},
+               {"URDF",                LTYPEI, AURDF},
+               {"URDD",                LTYPEI, AURDD},
+               {"NRMF",                LTYPEI, ANRMF},
+               {"NRMD",                LTYPEI, ANRMD},
+       */
+       {"ABSF", LTYPEI, arm.AABSF},
+       {"ABSD", LTYPEI, arm.AABSD},
+       {"SQRTF", LTYPEI, arm.ASQRTF},
+       {"SQRTD", LTYPEI, arm.ASQRTD},
+       {"CMPF", LTYPEL, arm.ACMPF},
+       {"CMPD", LTYPEL, arm.ACMPD},
+       {"ADDF", LTYPEK, arm.AADDF},
+       {"ADDD", LTYPEK, arm.AADDD},
+       {"SUBF", LTYPEK, arm.ASUBF},
+       {"SUBD", LTYPEK, arm.ASUBD},
+       {"MULF", LTYPEK, arm.AMULF},
+       {"MULD", LTYPEK, arm.AMULD},
+       {"DIVF", LTYPEK, arm.ADIVF},
+       {"DIVD", LTYPEK, arm.ADIVD},
+       {"B", LTYPE4, arm.AB},
+       {"BL", LTYPE4, arm.ABL},
+       {"BX", LTYPEBX, arm.ABX},
+       {"BEQ", LTYPE5, arm.ABEQ},
+       {"BNE", LTYPE5, arm.ABNE},
+       {"BCS", LTYPE5, arm.ABCS},
+       {"BHS", LTYPE5, arm.ABHS},
+       {"BCC", LTYPE5, arm.ABCC},
+       {"BLO", LTYPE5, arm.ABLO},
+       {"BMI", LTYPE5, arm.ABMI},
+       {"BPL", LTYPE5, arm.ABPL},
+       {"BVS", LTYPE5, arm.ABVS},
+       {"BVC", LTYPE5, arm.ABVC},
+       {"BHI", LTYPE5, arm.ABHI},
+       {"BLS", LTYPE5, arm.ABLS},
+       {"BGE", LTYPE5, arm.ABGE},
+       {"BLT", LTYPE5, arm.ABLT},
+       {"BGT", LTYPE5, arm.ABGT},
+       {"BLE", LTYPE5, arm.ABLE},
+       {"BCASE", LTYPE5, arm.ABCASE},
+       {"SWI", LTYPE6, arm.ASWI},
+       {"CMP", LTYPE7, arm.ACMP},
+       {"TST", LTYPE7, arm.ATST},
+       {"TEQ", LTYPE7, arm.ATEQ},
+       {"CMN", LTYPE7, arm.ACMN},
+       {"MOVM", LTYPE8, arm.AMOVM},
+       {"SWPBU", LTYPE9, arm.ASWPBU},
+       {"SWPW", LTYPE9, arm.ASWPW},
+       {"RET", LTYPEA, arm.ARET},
+       {"RFE", LTYPEA, arm.ARFE},
+       {"TEXT", LTYPEB, arm.ATEXT},
+       {"GLOBL", LTYPEB, arm.AGLOBL},
+       {"DATA", LTYPEC, arm.ADATA},
+       {"CASE", LTYPED, arm.ACASE},
+       {"END", LTYPEE, arm.AEND},
+       {"WORD", LTYPEH, arm.AWORD},
+       {"NOP", LTYPEI, arm.ANOP},
+       {"MCR", LTYPEJ, 0},
+       {"MRC", LTYPEJ, 1},
+       {"PLD", LTYPEPLD, arm.APLD},
+       {"UNDEF", LTYPEE, arm.AUNDEF},
+       {"CLZ", LTYPE2, arm.ACLZ},
+       {"MULWT", LTYPE1, arm.AMULWT},
+       {"MULWB", LTYPE1, arm.AMULWB},
+       {"MULAWT", LTYPEN, arm.AMULAWT},
+       {"MULAWB", LTYPEN, arm.AMULAWB},
+       {"USEFIELD", LTYPEN, arm.AUSEFIELD},
+       {"PCDATA", LTYPEPC, arm.APCDATA},
+       {"FUNCDATA", LTYPEF, arm.AFUNCDATA},
+}
+
+func cinit() {
+       nullgen.Type = arm.D_NONE
+       nullgen.Name = arm.D_NONE
+       nullgen.Reg = arm.NREG
+}
+
+func isreg(g *obj.Addr) bool {
+       return true
+}
+
+func cclean() {
+       outcode(arm.AEND, Always, &nullgen, arm.NREG, &nullgen)
+}
+
+var bcode = []int{
+       arm.ABEQ,
+       arm.ABNE,
+       arm.ABCS,
+       arm.ABCC,
+       arm.ABMI,
+       arm.ABPL,
+       arm.ABVS,
+       arm.ABVC,
+       arm.ABHI,
+       arm.ABLS,
+       arm.ABGE,
+       arm.ABLT,
+       arm.ABGT,
+       arm.ABLE,
+       arm.AB,
+       arm.ANOP,
+}
+
+var lastpc *obj.Prog
+
+func outcode(a, scond int32, g1 *obj.Addr, reg int32, g2 *obj.Addr) {
+       var p *obj.Prog
+       var pl *obj.Plist
+
+       /* hack to make B.NE etc. work: turn it into the corresponding conditional */
+       if a == arm.AB {
+               a = int32(bcode[scond&0xf])
+               scond = (scond &^ 0xf) | Always
+       }
+
+       if asm.Pass == 1 {
+               goto out
+       }
+
+       p = new(obj.Prog)
+       *p = obj.Prog{}
+       p.Ctxt = asm.Ctxt
+       p.As = int16(a)
+       p.Lineno = stmtline
+       p.Scond = uint8(scond)
+       p.From = *g1
+       p.Reg = uint8(reg)
+       p.To = *g2
+       p.Pc = int64(asm.PC)
+
+       if lastpc == nil {
+               pl = obj.Linknewplist(asm.Ctxt)
+               pl.Firstpc = p
+       } else {
+               lastpc.Link = p
+       }
+       lastpc = p
+
+out:
+       if a != arm.AGLOBL && a != arm.ADATA {
+               asm.PC++
+       }
+}
diff --git a/src/cmd/new5a/y.go b/src/cmd/new5a/y.go
new file mode 100644 (file)
index 0000000..f63bade
--- /dev/null
@@ -0,0 +1,1315 @@
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/arm"
+)
+
+//line a.y:41
+type yySymType struct {
+       yys  int
+       sym  *asm.Sym
+       lval int32
+       dval float64
+       sval string
+       addr obj.Addr
+}
+
+const LTYPE1 = 57346
+const LTYPE2 = 57347
+const LTYPE3 = 57348
+const LTYPE4 = 57349
+const LTYPE5 = 57350
+const LTYPE6 = 57351
+const LTYPE7 = 57352
+const LTYPE8 = 57353
+const LTYPE9 = 57354
+const LTYPEA = 57355
+const LTYPEB = 57356
+const LTYPEC = 57357
+const LTYPED = 57358
+const LTYPEE = 57359
+const LTYPEG = 57360
+const LTYPEH = 57361
+const LTYPEI = 57362
+const LTYPEJ = 57363
+const LTYPEK = 57364
+const LTYPEL = 57365
+const LTYPEM = 57366
+const LTYPEN = 57367
+const LTYPEBX = 57368
+const LTYPEPLD = 57369
+const LCONST = 57370
+const LSP = 57371
+const LSB = 57372
+const LFP = 57373
+const LPC = 57374
+const LTYPEX = 57375
+const LTYPEPC = 57376
+const LTYPEF = 57377
+const LR = 57378
+const LREG = 57379
+const LF = 57380
+const LFREG = 57381
+const LC = 57382
+const LCREG = 57383
+const LPSR = 57384
+const LFCR = 57385
+const LCOND = 57386
+const LS = 57387
+const LAT = 57388
+const LFCONST = 57389
+const LSCONST = 57390
+const LNAME = 57391
+const LLAB = 57392
+const LVAR = 57393
+
+var yyToknames = []string{
+       "'|'",
+       "'^'",
+       "'&'",
+       "'<'",
+       "'>'",
+       "'+'",
+       "'-'",
+       "'*'",
+       "'/'",
+       "'%'",
+       "LTYPE1",
+       "LTYPE2",
+       "LTYPE3",
+       "LTYPE4",
+       "LTYPE5",
+       "LTYPE6",
+       "LTYPE7",
+       "LTYPE8",
+       "LTYPE9",
+       "LTYPEA",
+       "LTYPEB",
+       "LTYPEC",
+       "LTYPED",
+       "LTYPEE",
+       "LTYPEG",
+       "LTYPEH",
+       "LTYPEI",
+       "LTYPEJ",
+       "LTYPEK",
+       "LTYPEL",
+       "LTYPEM",
+       "LTYPEN",
+       "LTYPEBX",
+       "LTYPEPLD",
+       "LCONST",
+       "LSP",
+       "LSB",
+       "LFP",
+       "LPC",
+       "LTYPEX",
+       "LTYPEPC",
+       "LTYPEF",
+       "LR",
+       "LREG",
+       "LF",
+       "LFREG",
+       "LC",
+       "LCREG",
+       "LPSR",
+       "LFCR",
+       "LCOND",
+       "LS",
+       "LAT",
+       "LFCONST",
+       "LSCONST",
+       "LNAME",
+       "LLAB",
+       "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+       -1, 1,
+       1, -1,
+       -2, 2,
+       -1, 194,
+       67, 59,
+       -2, 48,
+}
+
+const yyNprod = 130
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 694
+
+var yyAct = []int{
+
+       123, 317, 71, 83, 98, 104, 200, 77, 82, 193,
+       89, 127, 271, 73, 113, 85, 3, 106, 227, 134,
+       327, 88, 87, 313, 76, 52, 52, 101, 102, 293,
+       283, 278, 84, 84, 270, 72, 81, 81, 70, 69,
+       84, 84, 84, 142, 269, 268, 81, 257, 84, 220,
+       114, 118, 323, 120, 310, 97, 99, 110, 75, 51,
+       60, 131, 132, 133, 103, 103, 294, 138, 140, 143,
+       137, 144, 103, 90, 121, 149, 92, 204, 111, 246,
+       93, 91, 112, 148, 195, 188, 136, 163, 101, 102,
+       156, 94, 145, 146, 157, 162, 43, 45, 151, 147,
+       108, 126, 302, 251, 106, 252, 62, 101, 102, 57,
+       56, 179, 149, 165, 184, 250, 95, 84, 44, 329,
+       194, 81, 322, 186, 182, 109, 320, 189, 316, 116,
+       199, 198, 122, 124, 206, 207, 197, 314, 54, 90,
+       209, 300, 92, 299, 44, 296, 93, 91, 187, 289,
+       286, 84, 222, 282, 260, 81, 256, 255, 218, 219,
+       44, 55, 217, 216, 215, 84, 131, 229, 59, 81,
+       214, 58, 212, 90, 211, 190, 92, 196, 192, 242,
+       93, 91, 84, 230, 191, 181, 81, 232, 233, 234,
+       235, 236, 249, 180, 239, 240, 241, 247, 178, 44,
+       164, 150, 125, 243, 86, 244, 219, 38, 37, 221,
+       254, 258, 34, 35, 36, 261, 262, 259, 264, 210,
+       57, 56, 228, 231, 272, 272, 272, 272, 273, 273,
+       273, 273, 72, 248, 213, 265, 277, 274, 275, 276,
+       245, 266, 267, 306, 57, 161, 158, 319, 318, 54,
+       135, 194, 305, 287, 194, 88, 87, 280, 281, 238,
+       285, 78, 292, 288, 226, 101, 102, 90, 295, 141,
+       92, 225, 55, 54, 93, 91, 224, 253, 100, 59,
+       291, 160, 58, 57, 56, 152, 153, 205, 154, 303,
+       237, 120, 160, 159, 53, 223, 55, 88, 263, 308,
+       307, 105, 105, 74, 129, 130, 58, 301, 7, 105,
+       312, 315, 54, 96, 304, 90, 2, 321, 92, 107,
+       1, 324, 93, 91, 325, 311, 117, 183, 101, 102,
+       101, 102, 284, 139, 155, 55, 309, 290, 8, 328,
+       119, 44, 74, 326, 0, 58, 0, 297, 0, 331,
+       9, 10, 11, 12, 14, 15, 16, 17, 18, 19,
+       20, 21, 22, 33, 0, 23, 24, 27, 25, 26,
+       28, 29, 13, 30, 57, 56, 202, 201, 203, 248,
+       31, 32, 176, 175, 174, 172, 173, 167, 168, 169,
+       170, 171, 88, 87, 0, 4, 0, 5, 101, 102,
+       6, 57, 56, 54, 90, 92, 0, 92, 0, 93,
+       91, 93, 91, 88, 87, 0, 0, 79, 80, 101,
+       102, 202, 201, 203, 53, 0, 55, 169, 170, 171,
+       54, 90, 0, 74, 92, 85, 58, 0, 93, 91,
+       88, 87, 0, 0, 79, 80, 128, 330, 129, 130,
+       0, 53, 0, 55, 0, 57, 56, 0, 0, 0,
+       74, 0, 85, 58, 176, 175, 174, 172, 173, 167,
+       168, 169, 170, 171, 176, 175, 174, 172, 173, 167,
+       168, 169, 170, 171, 54, 0, 57, 56, 0, 0,
+       57, 56, 0, 0, 57, 56, 202, 201, 203, 92,
+       0, 0, 0, 93, 91, 53, 0, 55, 57, 56,
+       0, 0, 57, 56, 74, 54, 0, 58, 0, 54,
+       0, 57, 56, 54, 0, 57, 56, 0, 0, 279,
+       0, 0, 0, 0, 228, 0, 0, 54, 55, 208,
+       0, 54, 55, 0, 185, 59, 55, 0, 58, 59,
+       54, 106, 58, 74, 54, 0, 58, 0, 115, 0,
+       55, 0, 53, 0, 55, 0, 0, 59, 0, 0,
+       58, 59, 0, 55, 58, 0, 0, 55, 0, 0,
+       59, 0, 0, 58, 74, 0, 0, 58, 176, 175,
+       174, 172, 173, 167, 168, 169, 170, 171, 176, 175,
+       174, 172, 173, 167, 168, 169, 170, 171, 176, 175,
+       174, 172, 173, 167, 168, 169, 170, 171, 90, 0,
+       0, 92, 0, 0, 0, 93, 91, 39, 167, 168,
+       169, 170, 171, 101, 102, 0, 0, 0, 40, 41,
+       42, 0, 0, 46, 47, 48, 49, 50, 0, 298,
+       61, 0, 63, 64, 65, 66, 67, 68, 177, 175,
+       174, 172, 173, 167, 168, 169, 170, 171, 166, 176,
+       175, 174, 172, 173, 167, 168, 169, 170, 171, 174,
+       172, 173, 167, 168, 169, 170, 171, 172, 173, 167,
+       168, 169, 170, 171,
+}
+var yyPact = []int{
+
+       -1000, -1000, 336, -1000, 150, 151, -1000, 144, 143, -1000,
+       -1000, -1000, -1000, 79, 79, -1000, -1000, -1000, -1000, -1000,
+       503, 503, -1000, 79, -1000, -1000, -1000, -1000, -1000, -1000,
+       446, 392, 392, 79, -1000, 512, 512, -1000, -1000, 34,
+       34, 365, 53, 10, 79, 499, 53, 34, 274, 276,
+       53, 137, 33, 439, -1000, -1000, 512, 512, 512, 512,
+       238, 579, -55, 344, -27, 344, 211, 579, 579, -1000,
+       31, -1000, 15, -1000, 100, 136, -1000, -1000, 30, -1000,
+       -1000, 15, -1000, -1000, 278, 235, -1000, -1000, 27, -1000,
+       -1000, -1000, -1000, 19, 135, -1000, 336, 604, -1000, 594,
+       133, -1000, -1000, -1000, -1000, -1000, 512, 128, 120, 485,
+       -1000, 228, -1000, -1000, 17, 295, 392, 119, 113, 228,
+       16, 112, 10, -1000, -1000, 481, 382, 9, 279, 512,
+       512, -1000, -1000, -1000, 470, 512, 79, -1000, 109, 107,
+       -1000, -1000, 224, 105, 99, 98, 97, 363, 457, -20,
+       392, 228, 288, 268, 263, 256, 15, -1000, -52, -1000,
+       -1000, 477, 512, 512, 392, -1000, -1000, 512, 512, 512,
+       512, 512, 283, 251, 512, 512, 512, -1000, 228, -1000,
+       228, 392, -1000, -1000, 11, 439, -1000, -1000, 191, -1000,
+       -1000, 228, 49, 36, 95, 363, 10, 92, -1000, 91,
+       -22, -1000, -1000, -1000, 382, 295, -1000, -1000, -1000, 89,
+       -1000, 207, 249, 165, 207, 512, 228, 228, -24, -25,
+       -1000, -1000, -35, 100, 100, 100, 100, 446, -1000, -38,
+       460, -1000, 416, 416, -1000, -1000, -1000, 512, 512, 680,
+       673, 654, 88, -1000, -1000, -1000, 337, 9, -39, 79,
+       228, 85, 228, 228, 84, 228, -53, -1000, -40, -2,
+       -55, -1000, -1000, 80, 79, 584, 78, 76, -1000, -1000,
+       -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+       619, 619, 228, -1000, -1000, 35, 516, -1000, -1000, 134,
+       -1000, -1000, 242, -1000, 203, -1000, 207, -1000, 228, -14,
+       228, -1000, -1000, -1000, -1000, 512, -46, -1000, 72, -1000,
+       228, 63, -1000, -1000, 197, 61, 228, 57, -1000, -16,
+       228, -1000, 197, 512, -49, 54, 378, -1000, -1000, 512,
+       -1000, 665,
+}
+var yyPgo = []int{
+
+       0, 4, 19, 339, 6, 11, 10, 0, 1, 12,
+       627, 9, 58, 14, 24, 336, 3, 261, 204, 333,
+       5, 7, 38, 8, 13, 327, 2, 278, 320, 316,
+       16, 313, 308, 82,
+}
+var yyR1 = []int{
+
+       0, 28, 29, 28, 31, 30, 30, 30, 30, 30,
+       30, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 10, 10, 10, 33, 33,
+       13, 13, 21, 21, 21, 21, 21, 18, 18, 11,
+       11, 11, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 25, 25, 24, 26, 26, 23, 23, 23, 27,
+       27, 27, 20, 14, 15, 17, 17, 17, 17, 9,
+       9, 6, 6, 6, 7, 7, 8, 8, 19, 19,
+       16, 16, 22, 22, 22, 5, 5, 5, 4, 4,
+       4, 1, 1, 1, 1, 1, 1, 3, 3, 2,
+       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+}
+var yyR2 = []int{
+
+       0, 0, 0, 3, 0, 4, 4, 4, 1, 2,
+       2, 7, 6, 5, 5, 5, 4, 4, 3, 3,
+       4, 6, 7, 7, 7, 6, 6, 3, 4, 6,
+       8, 6, 4, 3, 5, 5, 7, 6, 12, 7,
+       9, 2, 4, 4, 2, 0, 2, 2, 0, 2,
+       4, 2, 2, 2, 4, 2, 1, 2, 3, 1,
+       3, 3, 1, 1, 1, 4, 1, 1, 1, 1,
+       1, 1, 1, 3, 1, 4, 1, 4, 1, 1,
+       1, 1, 2, 1, 5, 4, 4, 4, 4, 1,
+       1, 1, 1, 4, 1, 1, 1, 4, 1, 1,
+       1, 4, 4, 5, 7, 0, 2, 2, 1, 1,
+       1, 1, 1, 2, 2, 2, 3, 0, 2, 1,
+       3, 3, 3, 3, 3, 4, 4, 3, 3, 3,
+}
+var yyChk = []int{
+
+       -1000, -28, -29, -30, 59, 61, 64, -32, 2, 14,
+       15, 16, 17, 36, 18, 19, 20, 21, 22, 23,
+       24, 25, 26, 29, 30, 32, 33, 31, 34, 35,
+       37, 44, 45, 27, 62, 63, 63, 64, 64, -10,
+       -10, -10, -10, -33, 65, -33, -10, -10, -10, -10,
+       -10, -22, -1, 59, 38, 61, 10, 9, 71, 68,
+       -22, -10, -33, -10, -10, -10, -10, -10, -10, -23,
+       -22, -26, -1, -24, 68, -12, -14, -21, -17, 52,
+       53, -1, -23, -16, -7, 70, -18, 49, 48, -6,
+       39, 47, 42, 46, -12, -33, -31, -2, -1, -2,
+       -27, 54, 55, -14, -20, -17, 70, -27, -12, -33,
+       -24, 68, -33, -13, -1, 59, -33, -27, -26, 66,
+       -1, -14, -33, -7, -33, 65, 68, -5, 7, 9,
+       10, -1, -1, -1, -2, 12, -14, -21, -16, -19,
+       -16, -18, 70, -16, -1, -14, -14, 68, 68, -7,
+       65, 68, 7, 8, 10, 56, -1, -23, 11, 58,
+       57, 10, 68, 68, 65, -30, 64, 9, 10, 11,
+       12, 13, 7, 8, 6, 5, 4, 64, 65, -1,
+       65, 65, -13, -25, -1, 59, -24, -22, 68, -5,
+       -12, 65, 65, -11, -7, 68, 65, -24, -20, -1,
+       -4, 40, 39, 41, 68, 8, -1, -1, 69, -1,
+       -33, 65, 65, 10, 65, 65, 65, 65, -6, -6,
+       69, -12, -7, 7, 8, 8, 8, 70, 57, -1,
+       -2, -12, -2, -2, -2, -2, -2, 7, 8, -2,
+       -2, -2, -7, -14, -14, -12, 68, -5, 42, -7,
+       66, 67, 10, -33, -24, 65, 65, 69, -4, -5,
+       65, -16, -16, 49, -16, -2, -14, -14, 69, 69,
+       69, -9, -7, -1, -9, -9, -9, -23, 69, 69,
+       -2, -2, 65, 69, -33, -11, 65, -7, -11, 65,
+       -33, -14, -20, 69, 68, -21, 65, -33, 65, 65,
+       65, -14, 67, -26, -14, 10, 40, -16, -7, -15,
+       68, -14, -1, 69, 65, -7, 65, -8, 51, 50,
+       65, -7, 65, 68, -7, -8, -2, 69, -3, 65,
+       69, -2,
+}
+var yyDef = []int{
+
+       1, -2, 0, 3, 0, 0, 8, 0, 0, 45,
+       45, 45, 45, 48, 48, 45, 45, 45, 45, 45,
+       0, 0, 45, 48, 45, 45, 45, 45, 45, 45,
+       0, 0, 0, 48, 4, 0, 0, 9, 10, 0,
+       0, 0, 48, 0, 48, 0, 48, 0, 0, 48,
+       48, 0, 0, 105, 111, 112, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+       76, 78, 0, 74, 0, 0, 62, 63, 64, 66,
+       67, 68, 69, 70, 83, 0, 56, 100, 0, 94,
+       95, 91, 92, 0, 0, 44, 0, 0, 119, 0,
+       0, 46, 47, 79, 80, 81, 0, 0, 0, 0,
+       18, 0, 49, 19, 0, 105, 0, 0, 0, 0,
+       0, 0, 0, 83, 27, 0, 0, 0, 0, 0,
+       0, 113, 114, 115, 0, 0, 48, 33, 0, 0,
+       98, 99, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 52, 53, 0, 55,
+       57, 0, 0, 0, 0, 5, 6, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 7, 0, 82,
+       0, 0, 16, 17, 0, 105, 71, 72, 0, 51,
+       20, 0, 0, 0, -2, 0, 0, 0, 28, 0,
+       0, 108, 109, 110, 0, 105, 106, 107, 116, 0,
+       32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       73, 42, 0, 0, 0, 0, 0, 0, 58, 0,
+       0, 43, 120, 121, 122, 123, 124, 0, 0, 127,
+       128, 129, 83, 13, 14, 15, 0, 51, 0, 48,
+       0, 0, 0, 0, 48, 0, 0, 102, 0, 0,
+       0, 34, 35, 100, 48, 0, 0, 0, 77, 75,
+       65, 85, 89, 90, 86, 87, 88, 54, 101, 93,
+       125, 126, 12, 50, 21, 0, 0, 60, 61, 48,
+       25, 26, 29, 103, 0, 31, 0, 37, 0, 0,
+       0, 11, 22, 23, 24, 0, 0, 36, 0, 39,
+       0, 0, 30, 104, 0, 0, 0, 0, 96, 0,
+       0, 40, 0, 0, 0, 117, 0, 84, 38, 0,
+       97, 118,
+}
+var yyTok1 = []int{
+
+       1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 70, 13, 6, 3,
+       68, 69, 11, 9, 65, 10, 3, 12, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 62, 64,
+       7, 63, 8, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 66, 3, 67, 5, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 4, 3, 71,
+}
+var yyTok2 = []int{
+
+       2, 3, 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,
+}
+var yyTok3 = []int{
+       0,
+}
+
+//line yaccpar:1
+
+/*     parser for yacc output  */
+
+var yyDebug = 0
+
+type yyLexer interface {
+       Lex(lval *yySymType) int
+       Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+       // 4 is TOKSTART above
+       if c >= 4 && c-4 < len(yyToknames) {
+               if yyToknames[c-4] != "" {
+                       return yyToknames[c-4]
+               }
+       }
+       return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+       if s >= 0 && s < len(yyStatenames) {
+               if yyStatenames[s] != "" {
+                       return yyStatenames[s]
+               }
+       }
+       return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+       c := 0
+       char := lex.Lex(lval)
+       if char <= 0 {
+               c = yyTok1[0]
+               goto out
+       }
+       if char < len(yyTok1) {
+               c = yyTok1[char]
+               goto out
+       }
+       if char >= yyPrivate {
+               if char < yyPrivate+len(yyTok2) {
+                       c = yyTok2[char-yyPrivate]
+                       goto out
+               }
+       }
+       for i := 0; i < len(yyTok3); i += 2 {
+               c = yyTok3[i+0]
+               if c == char {
+                       c = yyTok3[i+1]
+                       goto out
+               }
+       }
+
+out:
+       if c == 0 {
+               c = yyTok2[1] /* unknown char */
+       }
+       if yyDebug >= 3 {
+               __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+       }
+       return c
+}
+
+func yyParse(yylex yyLexer) int {
+       var yyn int
+       var yylval yySymType
+       var yyVAL yySymType
+       yyS := make([]yySymType, yyMaxDepth)
+
+       Nerrs := 0   /* number of errors */
+       Errflag := 0 /* error recovery flag */
+       yystate := 0
+       yychar := -1
+       yyp := -1
+       goto yystack
+
+ret0:
+       return 0
+
+ret1:
+       return 1
+
+yystack:
+       /* put a state and value onto the stack */
+       if yyDebug >= 4 {
+               __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+       }
+
+       yyp++
+       if yyp >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyS[yyp] = yyVAL
+       yyS[yyp].yys = yystate
+
+yynewstate:
+       yyn = yyPact[yystate]
+       if yyn <= yyFlag {
+               goto yydefault /* simple state */
+       }
+       if yychar < 0 {
+               yychar = yylex1(yylex, &yylval)
+       }
+       yyn += yychar
+       if yyn < 0 || yyn >= yyLast {
+               goto yydefault
+       }
+       yyn = yyAct[yyn]
+       if yyChk[yyn] == yychar { /* valid shift */
+               yychar = -1
+               yyVAL = yylval
+               yystate = yyn
+               if Errflag > 0 {
+                       Errflag--
+               }
+               goto yystack
+       }
+
+yydefault:
+       /* default state action */
+       yyn = yyDef[yystate]
+       if yyn == -2 {
+               if yychar < 0 {
+                       yychar = yylex1(yylex, &yylval)
+               }
+
+               /* look through exception table */
+               xi := 0
+               for {
+                       if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+                               break
+                       }
+                       xi += 2
+               }
+               for xi += 2; ; xi += 2 {
+                       yyn = yyExca[xi+0]
+                       if yyn < 0 || yyn == yychar {
+                               break
+                       }
+               }
+               yyn = yyExca[xi+1]
+               if yyn < 0 {
+                       goto ret0
+               }
+       }
+       if yyn == 0 {
+               /* error ... attempt to resume parsing */
+               switch Errflag {
+               case 0: /* brand new error */
+                       yylex.Error("syntax error")
+                       Nerrs++
+                       if yyDebug >= 1 {
+                               __yyfmt__.Printf("%s", yyStatname(yystate))
+                               __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+                       }
+                       fallthrough
+
+               case 1, 2: /* incompletely recovered error ... try again */
+                       Errflag = 3
+
+                       /* find a state where "error" is a legal shift action */
+                       for yyp >= 0 {
+                               yyn = yyPact[yyS[yyp].yys] + yyErrCode
+                               if yyn >= 0 && yyn < yyLast {
+                                       yystate = yyAct[yyn] /* simulate a shift of "error" */
+                                       if yyChk[yystate] == yyErrCode {
+                                               goto yystack
+                                       }
+                               }
+
+                               /* the current p has no shift on "error", pop stack */
+                               if yyDebug >= 2 {
+                                       __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+                               }
+                               yyp--
+                       }
+                       /* there is no state on the stack with an error shift ... abort */
+                       goto ret1
+
+               case 3: /* no shift yet; clobber input char */
+                       if yyDebug >= 2 {
+                               __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+                       }
+                       if yychar == yyEofCode {
+                               goto ret1
+                       }
+                       yychar = -1
+                       goto yynewstate /* try again in the same state */
+               }
+       }
+
+       /* reduction by production yyn */
+       if yyDebug >= 2 {
+               __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+       }
+
+       yynt := yyn
+       yypt := yyp
+       _ = yypt // guard against "declared and not used"
+
+       yyp -= yyR2[yyn]
+       // yyp is now the index of $0. Perform the default action. Iff the
+       // reduced production is Îµ, $1 is possibly out of range.
+       if yyp+1 >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyVAL = yyS[yyp+1]
+
+       /* consult goto table to find next state */
+       yyn = yyR1[yyn]
+       yyg := yyPgo[yyn]
+       yyj := yyg + yyS[yyp].yys + 1
+
+       if yyj >= yyLast {
+               yystate = yyAct[yyg]
+       } else {
+               yystate = yyAct[yyj]
+               if yyChk[yystate] != -yyn {
+                       yystate = yyAct[yyg]
+               }
+       }
+       // dummy call; replaced with literal code
+       switch yynt {
+
+       case 2:
+               //line a.y:73
+               {
+                       stmtline = asm.Lineno
+               }
+       case 4:
+               //line a.y:80
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+                               yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyS[yypt-1].sym.Type = LLAB
+                       yyS[yypt-1].sym.Value = int64(asm.PC)
+               }
+       case 6:
+               //line a.y:90
+               {
+                       yyS[yypt-3].sym.Type = LVAR
+                       yyS[yypt-3].sym.Value = int64(yyS[yypt-1].lval)
+               }
+       case 7:
+               //line a.y:95
+               {
+                       if yyS[yypt-3].sym.Value != int64(yyS[yypt-1].lval) {
+                               yyerror("redeclaration of %s", yyS[yypt-3].sym.Name)
+                       }
+                       yyS[yypt-3].sym.Value = int64(yyS[yypt-1].lval)
+               }
+       case 11:
+               //line a.y:110
+               {
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+               }
+       case 12:
+               //line a.y:114
+               {
+                       outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, yyS[yypt-1].lval, &nullgen)
+               }
+       case 13:
+               //line a.y:118
+               {
+                       outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 14:
+               //line a.y:125
+               {
+                       outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 15:
+               //line a.y:132
+               {
+                       outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 16:
+               //line a.y:139
+               {
+                       outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 17:
+               //line a.y:143
+               {
+                       outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 18:
+               //line a.y:150
+               {
+                       outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 19:
+               //line a.y:157
+               {
+                       outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 20:
+               //line a.y:164
+               {
+                       outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 21:
+               //line a.y:171
+               {
+                       outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, yyS[yypt-1].lval, &nullgen)
+               }
+       case 22:
+               //line a.y:178
+               {
+                       var g obj.Addr
+
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = int64(yyS[yypt-1].lval)
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, NREG, &g)
+               }
+       case 23:
+               //line a.y:187
+               {
+                       var g obj.Addr
+
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = int64(yyS[yypt-3].lval)
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &g, NREG, &yyS[yypt-0].addr)
+               }
+       case 24:
+               //line a.y:199
+               {
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-2].addr, int32(yyS[yypt-4].addr.Reg), &yyS[yypt-0].addr)
+               }
+       case 25:
+               //line a.y:203
+               {
+                       outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-1].addr, int32(yyS[yypt-3].addr.Reg), &yyS[yypt-3].addr)
+               }
+       case 26:
+               //line a.y:207
+               {
+                       outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-2].addr, int32(yyS[yypt-0].addr.Reg), &yyS[yypt-0].addr)
+               }
+       case 27:
+               //line a.y:214
+               {
+                       outcode(yyS[yypt-2].lval, yyS[yypt-1].lval, &nullgen, NREG, &nullgen)
+               }
+       case 28:
+               //line a.y:221
+               {
+                       asm.Settext(yyS[yypt-2].addr.Sym)
+                       yyS[yypt-0].addr.Type = D_CONST2
+                       yyS[yypt-0].addr.Offset2 = -obj.ArgsSizeUnknown
+                       outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, 0, &yyS[yypt-0].addr)
+               }
+       case 29:
+               //line a.y:228
+               {
+                       asm.Settext(yyS[yypt-4].addr.Sym)
+                       yyS[yypt-0].addr.Type = D_CONST2
+                       yyS[yypt-0].addr.Offset2 = -obj.ArgsSizeUnknown
+                       outcode(yyS[yypt-5].lval, Always, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+               }
+       case 30:
+               //line a.y:235
+               {
+                       asm.Settext(yyS[yypt-6].addr.Sym)
+                       yyS[yypt-2].addr.Type = D_CONST2
+                       yyS[yypt-2].addr.Offset2 = yyS[yypt-0].lval
+                       outcode(yyS[yypt-7].lval, Always, &yyS[yypt-6].addr, yyS[yypt-4].lval, &yyS[yypt-2].addr)
+               }
+       case 31:
+               //line a.y:245
+               {
+                       outcode(yyS[yypt-5].lval, Always, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+               }
+       case 32:
+               //line a.y:252
+               {
+                       outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 33:
+               //line a.y:259
+               {
+                       outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 34:
+               //line a.y:266
+               {
+                       outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 35:
+               //line a.y:270
+               {
+                       outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 36:
+               //line a.y:274
+               {
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+               }
+       case 37:
+               //line a.y:278
+               {
+                       outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, int32(yyS[yypt-1].addr.Reg), &nullgen)
+               }
+       case 38:
+               //line a.y:285
+               {
+                       var g obj.Addr
+
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = int64(
+                               (0xe << 24) | /* opcode */
+                                       (yyS[yypt-11].lval << 20) | /* MCR/MRC */
+                                       (yyS[yypt-10].lval << 28) | /* scond */
+                                       ((yyS[yypt-9].lval & 15) << 8) | /* coprocessor number */
+                                       ((yyS[yypt-7].lval & 7) << 21) | /* coprocessor operation */
+                                       ((yyS[yypt-5].lval & 15) << 12) | /* arm register */
+                                       ((yyS[yypt-3].lval & 15) << 16) | /* Crn */
+                                       ((yyS[yypt-1].lval & 15) << 0) | /* Crm */
+                                       ((yyS[yypt-0].lval & 7) << 5) | /* coprocessor information */
+                                       (1 << 4)) /* must be set */
+                       outcode(AMRC, Always, &nullgen, NREG, &g)
+               }
+       case 39:
+               //line a.y:297
+               {
+                       outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, int32(yyS[yypt-2].addr.Reg), &yyS[yypt-0].addr)
+               }
+       case 40:
+               //line a.y:305
+               {
+                       yyS[yypt-2].addr.Type = D_REGREG2
+                       yyS[yypt-2].addr.Offset = int64(yyS[yypt-0].lval)
+                       outcode(yyS[yypt-8].lval, yyS[yypt-7].lval, &yyS[yypt-6].addr, int32(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr)
+               }
+       case 41:
+               //line a.y:314
+               {
+                       outcode(yyS[yypt-1].lval, Always, &yyS[yypt-0].addr, NREG, &nullgen)
+               }
+       case 42:
+               //line a.y:321
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+                               yyerror("arguments to PCDATA must be integer constants")
+                       }
+                       outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 43:
+               //line a.y:331
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST {
+                               yyerror("index for FUNCDATA must be integer constant")
+                       }
+                       if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC && yyS[yypt-0].addr.Type != D_OREG {
+                               yyerror("value for FUNCDATA must be symbol reference")
+                       }
+                       outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 44:
+               //line a.y:344
+               {
+                       outcode(yyS[yypt-1].lval, Always, &nullgen, NREG, &nullgen)
+               }
+       case 45:
+               //line a.y:349
+               {
+                       yyVAL.lval = Always
+               }
+       case 46:
+               //line a.y:353
+               {
+                       yyVAL.lval = (yyS[yypt-1].lval & ^C_SCOND) | yyS[yypt-0].lval
+               }
+       case 47:
+               //line a.y:357
+               {
+                       yyVAL.lval = yyS[yypt-1].lval | yyS[yypt-0].lval
+               }
+       case 50:
+               //line a.y:366
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval) + int64(asm.PC)
+               }
+       case 51:
+               //line a.y:372
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       yyVAL.addr = nullgen
+                       if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+                               yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-1].sym.Value + int64(yyS[yypt-0].lval)
+               }
+       case 52:
+               //line a.y:383
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST
+                       yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+               }
+       case 53:
+               //line a.y:389
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       yyVAL.addr.Type = D_CONST
+               }
+       case 54:
+               //line a.y:394
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       yyVAL.addr.Type = D_OCONST
+               }
+       case 55:
+               //line a.y:399
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SCONST
+                       yyVAL.addr.U.Sval = yyS[yypt-0].sval
+               }
+       case 56:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 57:
+               //line a.y:408
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-0].dval
+               }
+       case 58:
+               //line a.y:414
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+               }
+       case 59:
+               //line a.y:422
+               {
+                       yyVAL.lval = 1 << uint(yyS[yypt-0].lval)
+               }
+       case 60:
+               //line a.y:426
+               {
+                       yyVAL.lval = 0
+                       for i := yyS[yypt-2].lval; i <= yyS[yypt-0].lval; i++ {
+                               yyVAL.lval |= 1 << uint(i)
+                       }
+                       for i := yyS[yypt-0].lval; i <= yyS[yypt-2].lval; i++ {
+                               yyVAL.lval |= 1 << uint(i)
+                       }
+               }
+       case 61:
+               //line a.y:436
+               {
+                       yyVAL.lval = (1 << uint(yyS[yypt-2].lval)) | yyS[yypt-0].lval
+               }
+       case 62:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 63:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 64:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 65:
+               //line a.y:445
+               {
+                       yyVAL.addr = yyS[yypt-3].addr
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 66:
+               //line a.y:450
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_PSR
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 67:
+               //line a.y:456
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FPCR
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 68:
+               //line a.y:462
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+               }
+       case 69:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 70:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 71:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 72:
+               //line a.y:473
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       if yyS[yypt-0].addr.Name != D_EXTERN && yyS[yypt-0].addr.Name != D_STATIC {
+                       }
+               }
+       case 73:
+               //line a.y:481
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = 0
+               }
+       case 74:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 75:
+               //line a.y:491
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+               }
+       case 76:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 77:
+               //line a.y:501
+               {
+                       yyVAL.addr = yyS[yypt-3].addr
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 78:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 79:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 80:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 81:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 82:
+               //line a.y:514
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST
+                       yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+               }
+       case 83:
+               //line a.y:522
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_REG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 84:
+               //line a.y:530
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_REGREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-3].lval)
+                       yyVAL.addr.Offset = int64(yyS[yypt-1].lval)
+               }
+       case 85:
+               //line a.y:539
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SHIFT
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (0 << 5)
+               }
+       case 86:
+               //line a.y:545
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SHIFT
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (1 << 5)
+               }
+       case 87:
+               //line a.y:551
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SHIFT
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (2 << 5)
+               }
+       case 88:
+               //line a.y:557
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SHIFT
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (3 << 5)
+               }
+       case 89:
+               //line a.y:565
+               {
+                       if yyVAL.lval < 0 || yyVAL.lval >= 16 {
+                               print("register value out of range\n")
+                       }
+                       yyVAL.lval = ((yyS[yypt-0].lval & 15) << 8) | (1 << 4)
+               }
+       case 90:
+               //line a.y:572
+               {
+                       if yyVAL.lval < 0 || yyVAL.lval >= 32 {
+                               print("shift value out of range\n")
+                       }
+                       yyVAL.lval = (yyS[yypt-0].lval & 31) << 7
+               }
+       case 91:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 92:
+               //line a.y:582
+               {
+                       yyVAL.lval = REGPC
+               }
+       case 93:
+               //line a.y:586
+               {
+                       if yyS[yypt-1].lval < 0 || yyS[yypt-1].lval >= NREG {
+                               print("register value out of range\n")
+                       }
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 94:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 95:
+               //line a.y:596
+               {
+                       yyVAL.lval = REGSP
+               }
+       case 96:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 97:
+               //line a.y:603
+               {
+                       if yyS[yypt-1].lval < 0 || yyS[yypt-1].lval >= NREG {
+                               print("register value out of range\n")
+                       }
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 98:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 99:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 100:
+               //line a.y:616
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 101:
+               //line a.y:622
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 102:
+               //line a.y:630
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = nil
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+               }
+       case 103:
+               //line a.y:638
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+               }
+       case 104:
+               //line a.y:646
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = D_STATIC
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+                       yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+               }
+       case 105:
+               //line a.y:655
+               {
+                       yyVAL.lval = 0
+               }
+       case 106:
+               //line a.y:659
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 107:
+               //line a.y:663
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 108:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 109:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 110:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 111:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 112:
+               //line a.y:675
+               {
+                       yyVAL.lval = int32(yyS[yypt-0].sym.Value)
+               }
+       case 113:
+               //line a.y:679
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 114:
+               //line a.y:683
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 115:
+               //line a.y:687
+               {
+                       yyVAL.lval = ^yyS[yypt-0].lval
+               }
+       case 116:
+               //line a.y:691
+               {
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 117:
+               //line a.y:696
+               {
+                       yyVAL.lval = 0
+               }
+       case 118:
+               //line a.y:700
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 119:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 120:
+               //line a.y:707
+               {
+                       yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+               }
+       case 121:
+               //line a.y:711
+               {
+                       yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+               }
+       case 122:
+               //line a.y:715
+               {
+                       yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+               }
+       case 123:
+               //line a.y:719
+               {
+                       yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+               }
+       case 124:
+               //line a.y:723
+               {
+                       yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+               }
+       case 125:
+               //line a.y:727
+               {
+                       yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+               }
+       case 126:
+               //line a.y:731
+               {
+                       yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+               }
+       case 127:
+               //line a.y:735
+               {
+                       yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+               }
+       case 128:
+               //line a.y:739
+               {
+                       yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+               }
+       case 129:
+               //line a.y:743
+               {
+                       yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+               }
+       }
+       goto yystack /* stack new state and value */
+}
diff --git a/src/cmd/new6a/a.y b/src/cmd/new6a/a.y
new file mode 100644 (file)
index 0000000..03a6c2d
--- /dev/null
@@ -0,0 +1,693 @@
+// Inferno utils/6a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
+//
+//     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.
+
+%{
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/x86"
+)
+%}
+
+%union {
+       sym *asm.Sym
+       lval int64
+       dval float64
+       sval string
+       addr obj.Addr
+       addr2 Addr2
+}
+
+%left  '|'
+%left  '^'
+%left  '&'
+%left  '<' '>'
+%left  '+' '-'
+%left  '*' '/' '%'
+%token <lval>  LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
+%token <lval>  LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC
+%token <lval>  LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF
+%token <lval>  LCONST LFP LPC LSB
+%token <lval>  LBREG LLREG LSREG LFREG LMREG LXREG
+%token <dval>  LFCONST
+%token <sval>  LSCONST LSP
+%token <sym>   LNAME LLAB LVAR
+%type  <lval>  con con2 expr pointer offset
+%type  <addr>  mem imm imm2 reg nam rel rem rim rom omem nmem
+%type  <addr2> nonnon nonrel nonrem rimnon rimrem remrim
+%type  <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
+%type  <addr2> spec10 spec11 spec12 spec13
+%%
+prog:
+|      prog 
+       {
+               stmtline = asm.Lineno;
+       }
+       line
+
+line:
+       LNAME ':'
+       {
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
+       }
+       line
+|      ';'
+|      inst ';'
+|      error ';'
+
+inst:
+       LNAME '=' expr
+       {
+               $1.Type = LVAR;
+               $1.Value = $3;
+       }
+|      LVAR '=' expr
+       {
+               if $1.Value != $3 {
+                       yyerror("redeclaration of %s", $1.Name);
+               }
+               $1.Value = $3;
+       }
+|      LTYPE0 nonnon   { outcode(int($1), &$2); }
+|      LTYPE1 nonrem   { outcode(int($1), &$2); }
+|      LTYPE2 rimnon   { outcode(int($1), &$2); }
+|      LTYPE3 rimrem   { outcode(int($1), &$2); }
+|      LTYPE4 remrim   { outcode(int($1), &$2); }
+|      LTYPER nonrel   { outcode(int($1), &$2); }
+|      LTYPED spec1    { outcode(int($1), &$2); }
+|      LTYPET spec2    { outcode(int($1), &$2); }
+|      LTYPEC spec3    { outcode(int($1), &$2); }
+|      LTYPEN spec4    { outcode(int($1), &$2); }
+|      LTYPES spec5    { outcode(int($1), &$2); }
+|      LTYPEM spec6    { outcode(int($1), &$2); }
+|      LTYPEI spec7    { outcode(int($1), &$2); }
+|      LTYPEXC spec8   { outcode(int($1), &$2); }
+|      LTYPEX spec9    { outcode(int($1), &$2); }
+|      LTYPERT spec10  { outcode(int($1), &$2); }
+|      LTYPEG spec11   { outcode(int($1), &$2); }
+|      LTYPEPC spec12  { outcode(int($1), &$2); }
+|      LTYPEF spec13   { outcode(int($1), &$2); }
+
+nonnon:
+       {
+               $$.from = nullgen;
+               $$.to = nullgen;
+       }
+|      ','
+       {
+               $$.from = nullgen;
+               $$.to = nullgen;
+       }
+
+rimrem:
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+remrim:
+       rem ',' rim
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+rimnon:
+       rim ','
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+
+nonrem:
+       ',' rem
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rem
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+
+nonrel:
+       ',' rel
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rel
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+|      imm ',' rel
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec1: /* DATA */
+       nam '/' con ',' imm
+       {
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec2: /* TEXT */
+       mem ',' imm2
+       {
+               asm.Settext($1.Sym);
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      mem ',' con ',' imm2
+       {
+               asm.Settext($1.Sym);
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec3: /* JMP/CALL */
+       ',' rom
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rom
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+
+spec4: /* NOP */
+       nonnon
+|      nonrem
+
+spec5: /* SHL/SHR */
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      rim ',' rem ':' LLREG
+       {
+               $$.from = $1;
+               $$.to = $3;
+               if $$.from.Index != x86.D_NONE {
+                       yyerror("dp shift with lhs index");
+               }
+               $$.from.Index = uint8($5);
+       }
+
+spec6: /* MOVW/MOVL */
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      rim ',' rem ':' LSREG
+       {
+               $$.from = $1;
+               $$.to = $3;
+               if $$.to.Index != x86.D_NONE {
+                       yyerror("dp move with lhs index");
+               }
+               $$.to.Index = uint8($5);
+       }
+
+spec7:
+       rim ','
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec8: /* CMPPS/CMPPD */
+       reg ',' rem ',' con
+       {
+               $$.from = $1;
+               $$.to = $3;
+               $$.to.Offset = $5;
+       }
+
+spec9: /* shufl */
+       imm ',' rem ',' reg
+       {
+               $$.from = $3;
+               $$.to = $5;
+               if $1.Type != x86.D_CONST {
+                       yyerror("illegal constant");
+               }
+               $$.to.Offset = $1.Offset;
+       }
+
+spec10:        /* RET/RETF */
+       {
+               $$.from = nullgen;
+               $$.to = nullgen;
+       }
+|      imm
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+
+spec11:        /* GLOBL */
+       mem ',' imm
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      mem ',' con ',' imm
+       {
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec12:        /* asm.PCDATA */
+       rim ',' rim
+       {
+               if $1.Type != x86.D_CONST || $3.Type != x86.D_CONST {
+                       yyerror("arguments to asm.PCDATA must be integer constants");
+               }
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec13:        /* FUNCDATA */
+       rim ',' rim
+       {
+               if $1.Type != x86.D_CONST {
+                       yyerror("index for FUNCDATA must be integer constant");
+               }
+               if $3.Type != x86.D_EXTERN && $3.Type != x86.D_STATIC {
+                       yyerror("value for FUNCDATA must be symbol reference");
+               }
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+rem:
+       reg
+|      mem
+
+rom:
+       rel
+|      nmem
+|      '*' reg
+       {
+               $$ = $2;
+       }
+|      '*' omem
+       {
+               $$ = $2;
+       }
+|      reg
+|      omem
+
+rim:
+       rem
+|      imm
+
+rel:
+       con '(' LPC ')'
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
+       }
+|      LNAME offset
+       {
+               $1 = asm.LabelLookup($1);
+               $$ = nullgen;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname);
+               }
+               $$.Type = x86.D_BRANCH;
+               $$.Offset = $1.Value + $2;
+       }
+
+reg:
+       LBREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LFREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LLREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LMREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LSP
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_SP;
+       }
+|      LSREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LXREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+imm2:
+       '$' con2
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_CONST;
+               $$.Offset = $2;
+       }
+
+imm:
+       '$' con
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_CONST;
+               $$.Offset = $2;
+       }
+|      '$' nam
+       {
+               $$ = $2;
+               $$.Index = uint8($2.Type);
+               $$.Type = x86.D_ADDR;
+               /*
+               if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
+                       yyerror("constant cannot be automatic: %s",
+                               $2.sym.Name);
+                */
+       }
+|      '$' LSCONST
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_SCONST;
+               $$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
+       }
+|      '$' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_FCONST;
+               $$.U.Dval = $2;
+       }
+|      '$' '(' LFCONST ')'
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_FCONST;
+               $$.U.Dval = $3;
+       }
+|      '$' '(' '-' LFCONST ')'
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_FCONST;
+               $$.U.Dval = -$4;
+       }
+|      '$' '-' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_FCONST;
+               $$.U.Dval = -$3;
+       }
+
+mem:
+       omem
+|      nmem
+
+omem:
+       con
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_INDIR+x86.D_NONE;
+               $$.Offset = $1;
+       }
+|      con '(' LLREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$3);
+               $$.Offset = $1;
+       }
+|      con '(' LSP ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+x86.D_SP);
+               $$.Offset = $1;
+       }
+|      con '(' LSREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$3);
+               $$.Offset = $1;
+       }
+|      con '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+x86.D_NONE);
+               $$.Offset = $1;
+               $$.Index = uint8($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
+       }
+|      con '(' LLREG ')' '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$3);
+               $$.Offset = $1;
+               $$.Index = uint8($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
+       }
+|      con '(' LLREG ')' '(' LSREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$3);
+               $$.Offset = $1;
+               $$.Index = uint8($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
+       }
+|      '(' LLREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$2);
+       }
+|      '(' LSP ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+x86.D_SP);
+       }
+|      '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+x86.D_NONE);
+               $$.Index = uint8($2);
+               $$.Scale = int8($4);
+               checkscale($$.Scale);
+       }
+|      '(' LLREG ')' '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(x86.D_INDIR+$2);
+               $$.Index = uint8($5);
+               $$.Scale = int8($7);
+               checkscale($$.Scale);
+       }
+
+nmem:
+       nam
+       {
+               $$ = $1;
+       }
+|      nam '(' LLREG '*' con ')'
+       {
+               $$ = $1;
+               $$.Index = uint8($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
+       }
+
+nam:
+       LNAME offset '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
+       }
+|      LNAME '<' '>' offset '(' LSB ')'
+       {
+               $$ = nullgen;
+               $$.Type = x86.D_STATIC;
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = $4;
+       }
+
+offset:
+       {
+               $$ = 0;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+
+pointer:
+       LSB
+|      LSP
+       {
+               $$ = x86.D_AUTO;
+       }
+|      LFP
+
+con:
+       LCONST
+|      LVAR
+       {
+               $$ = $1.Value;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '~' con
+       {
+               $$ = ^$2;
+       }
+|      '(' expr ')'
+       {
+               $$ = $2;
+       }
+
+con2:
+       LCONST
+       {
+               $$ = int64(uint64($1 & 0xffffffff) + (obj.ArgsSizeUnknown<<32))
+       }
+|      '-' LCONST
+       {
+               $$ = int64(uint64(-$2 & 0xffffffff) + (obj.ArgsSizeUnknown<<32))
+       }
+|      LCONST '-' LCONST
+       {
+               $$ = ($1 & 0xffffffff) + (($3 & 0xffff) << 32);
+       }
+|      '-' LCONST '-' LCONST
+       {
+               $$ = (-$2 & 0xffffffff) + (($4 & 0xffff) << 32);
+       }
+
+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 << uint($4);
+       }
+|      expr '>' '>' expr
+       {
+               $$ = $1 >> uint($4);
+       }
+|      expr '&' expr
+       {
+               $$ = $1 & $3;
+       }
+|      expr '^' expr
+       {
+               $$ = $1 ^ $3;
+       }
+|      expr '|' expr
+       {
+               $$ = $1 | $3;
+       }
diff --git a/src/cmd/new6a/lex.go b/src/cmd/new6a/lex.go
new file mode 100644 (file)
index 0000000..98a039e
--- /dev/null
@@ -0,0 +1,979 @@
+// Inferno utils/6a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.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.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/x86"
+)
+
+var (
+       yyerror  = asm.Yyerror
+       nullgen  obj.Addr
+       stmtline int32
+)
+
+func main() {
+       cinit()
+
+       asm.LSCONST = LSCONST
+       asm.LCONST = LCONST
+       asm.LFCONST = LFCONST
+       asm.LNAME = LNAME
+       asm.LVAR = LVAR
+       asm.LLAB = LLAB
+
+       asm.Thechar = '6'
+       asm.Thestring = "amd64"
+       asm.Thelinkarch = &x86.Linkamd64
+       asm.Arches = map[string]*obj.LinkArch{
+               "amd64p32": &x86.Linkamd64p32,
+       }
+
+       asm.Lexinit = lexinit
+       asm.Cclean = cclean
+       asm.Yyparse = yyparse
+
+       asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+       var av asm.Yylval
+       tok := asm.Yylex(&av)
+       v.sym = av.Sym
+       v.lval = av.Lval
+       v.sval = av.Sval
+       v.dval = av.Dval
+       return tok
+}
+
+func (yy) Error(msg string) {
+       asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+       yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+       {"SP", LSP, x86.D_AUTO},
+       {"SB", LSB, x86.D_EXTERN},
+       {"FP", LFP, x86.D_PARAM},
+       {"PC", LPC, x86.D_BRANCH},
+       {"AL", LBREG, x86.D_AL},
+       {"CL", LBREG, x86.D_CL},
+       {"DL", LBREG, x86.D_DL},
+       {"BL", LBREG, x86.D_BL},
+       /*      "SPB",          LBREG,  D_SPB,  */
+       {"SIB", LBREG, x86.D_SIB},
+       {"DIB", LBREG, x86.D_DIB},
+       {"BPB", LBREG, x86.D_BPB},
+       {"R8B", LBREG, x86.D_R8B},
+       {"R9B", LBREG, x86.D_R9B},
+       {"R10B", LBREG, x86.D_R10B},
+       {"R11B", LBREG, x86.D_R11B},
+       {"R12B", LBREG, x86.D_R12B},
+       {"R13B", LBREG, x86.D_R13B},
+       {"R14B", LBREG, x86.D_R14B},
+       {"R15B", LBREG, x86.D_R15B},
+       {"AH", LBREG, x86.D_AH},
+       {"CH", LBREG, x86.D_CH},
+       {"DH", LBREG, x86.D_DH},
+       {"BH", LBREG, x86.D_BH},
+       {"AX", LLREG, x86.D_AX},
+       {"CX", LLREG, x86.D_CX},
+       {"DX", LLREG, x86.D_DX},
+       {"BX", LLREG, x86.D_BX},
+
+       /*      "SP",           LLREG,  D_SP,   */
+       {"BP", LLREG, x86.D_BP},
+       {"SI", LLREG, x86.D_SI},
+       {"DI", LLREG, x86.D_DI},
+       {"R8", LLREG, x86.D_R8},
+       {"R9", LLREG, x86.D_R9},
+       {"R10", LLREG, x86.D_R10},
+       {"R11", LLREG, x86.D_R11},
+       {"R12", LLREG, x86.D_R12},
+       {"R13", LLREG, x86.D_R13},
+       {"R14", LLREG, x86.D_R14},
+       {"R15", LLREG, x86.D_R15},
+       {"RARG", LLREG, x86.REGARG},
+       {"F0", LFREG, x86.D_F0 + 0},
+       {"F1", LFREG, x86.D_F0 + 1},
+       {"F2", LFREG, x86.D_F0 + 2},
+       {"F3", LFREG, x86.D_F0 + 3},
+       {"F4", LFREG, x86.D_F0 + 4},
+       {"F5", LFREG, x86.D_F0 + 5},
+       {"F6", LFREG, x86.D_F0 + 6},
+       {"F7", LFREG, x86.D_F0 + 7},
+       {"M0", LMREG, x86.D_M0 + 0},
+       {"M1", LMREG, x86.D_M0 + 1},
+       {"M2", LMREG, x86.D_M0 + 2},
+       {"M3", LMREG, x86.D_M0 + 3},
+       {"M4", LMREG, x86.D_M0 + 4},
+       {"M5", LMREG, x86.D_M0 + 5},
+       {"M6", LMREG, x86.D_M0 + 6},
+       {"M7", LMREG, x86.D_M0 + 7},
+       {"X0", LXREG, x86.D_X0 + 0},
+       {"X1", LXREG, x86.D_X0 + 1},
+       {"X2", LXREG, x86.D_X0 + 2},
+       {"X3", LXREG, x86.D_X0 + 3},
+       {"X4", LXREG, x86.D_X0 + 4},
+       {"X5", LXREG, x86.D_X0 + 5},
+       {"X6", LXREG, x86.D_X0 + 6},
+       {"X7", LXREG, x86.D_X0 + 7},
+       {"X8", LXREG, x86.D_X0 + 8},
+       {"X9", LXREG, x86.D_X0 + 9},
+       {"X10", LXREG, x86.D_X0 + 10},
+       {"X11", LXREG, x86.D_X0 + 11},
+       {"X12", LXREG, x86.D_X0 + 12},
+       {"X13", LXREG, x86.D_X0 + 13},
+       {"X14", LXREG, x86.D_X0 + 14},
+       {"X15", LXREG, x86.D_X0 + 15},
+       {"CS", LSREG, x86.D_CS},
+       {"SS", LSREG, x86.D_SS},
+       {"DS", LSREG, x86.D_DS},
+       {"ES", LSREG, x86.D_ES},
+       {"FS", LSREG, x86.D_FS},
+       {"GS", LSREG, x86.D_GS},
+       {"GDTR", LBREG, x86.D_GDTR},
+       {"IDTR", LBREG, x86.D_IDTR},
+       {"LDTR", LBREG, x86.D_LDTR},
+       {"MSW", LBREG, x86.D_MSW},
+       {"TASK", LBREG, x86.D_TASK},
+       {"CR0", LBREG, x86.D_CR + 0},
+       {"CR1", LBREG, x86.D_CR + 1},
+       {"CR2", LBREG, x86.D_CR + 2},
+       {"CR3", LBREG, x86.D_CR + 3},
+       {"CR4", LBREG, x86.D_CR + 4},
+       {"CR5", LBREG, x86.D_CR + 5},
+       {"CR6", LBREG, x86.D_CR + 6},
+       {"CR7", LBREG, x86.D_CR + 7},
+       {"CR8", LBREG, x86.D_CR + 8},
+       {"CR9", LBREG, x86.D_CR + 9},
+       {"CR10", LBREG, x86.D_CR + 10},
+       {"CR11", LBREG, x86.D_CR + 11},
+       {"CR12", LBREG, x86.D_CR + 12},
+       {"CR13", LBREG, x86.D_CR + 13},
+       {"CR14", LBREG, x86.D_CR + 14},
+       {"CR15", LBREG, x86.D_CR + 15},
+       {"DR0", LBREG, x86.D_DR + 0},
+       {"DR1", LBREG, x86.D_DR + 1},
+       {"DR2", LBREG, x86.D_DR + 2},
+       {"DR3", LBREG, x86.D_DR + 3},
+       {"DR4", LBREG, x86.D_DR + 4},
+       {"DR5", LBREG, x86.D_DR + 5},
+       {"DR6", LBREG, x86.D_DR + 6},
+       {"DR7", LBREG, x86.D_DR + 7},
+       {"TR0", LBREG, x86.D_TR + 0},
+       {"TR1", LBREG, x86.D_TR + 1},
+       {"TR2", LBREG, x86.D_TR + 2},
+       {"TR3", LBREG, x86.D_TR + 3},
+       {"TR4", LBREG, x86.D_TR + 4},
+       {"TR5", LBREG, x86.D_TR + 5},
+       {"TR6", LBREG, x86.D_TR + 6},
+       {"TR7", LBREG, x86.D_TR + 7},
+       {"TLS", LSREG, x86.D_TLS},
+       {"AAA", LTYPE0, x86.AAAA},
+       {"AAD", LTYPE0, x86.AAAD},
+       {"AAM", LTYPE0, x86.AAAM},
+       {"AAS", LTYPE0, x86.AAAS},
+       {"ADCB", LTYPE3, x86.AADCB},
+       {"ADCL", LTYPE3, x86.AADCL},
+       {"ADCQ", LTYPE3, x86.AADCQ},
+       {"ADCW", LTYPE3, x86.AADCW},
+       {"ADDB", LTYPE3, x86.AADDB},
+       {"ADDL", LTYPE3, x86.AADDL},
+       {"ADDQ", LTYPE3, x86.AADDQ},
+       {"ADDW", LTYPE3, x86.AADDW},
+       {"ADJSP", LTYPE2, x86.AADJSP},
+       {"ANDB", LTYPE3, x86.AANDB},
+       {"ANDL", LTYPE3, x86.AANDL},
+       {"ANDQ", LTYPE3, x86.AANDQ},
+       {"ANDW", LTYPE3, x86.AANDW},
+       {"ARPL", LTYPE3, x86.AARPL},
+       {"BOUNDL", LTYPE3, x86.ABOUNDL},
+       {"BOUNDW", LTYPE3, x86.ABOUNDW},
+       {"BSFL", LTYPE3, x86.ABSFL},
+       {"BSFQ", LTYPE3, x86.ABSFQ},
+       {"BSFW", LTYPE3, x86.ABSFW},
+       {"BSRL", LTYPE3, x86.ABSRL},
+       {"BSRQ", LTYPE3, x86.ABSRQ},
+       {"BSRW", LTYPE3, x86.ABSRW},
+       {"BSWAPL", LTYPE1, x86.ABSWAPL},
+       {"BSWAPQ", LTYPE1, x86.ABSWAPQ},
+       {"BTCL", LTYPE3, x86.ABTCL},
+       {"BTCQ", LTYPE3, x86.ABTCQ},
+       {"BTCW", LTYPE3, x86.ABTCW},
+       {"BTL", LTYPE3, x86.ABTL},
+       {"BTQ", LTYPE3, x86.ABTQ},
+       {"BTRL", LTYPE3, x86.ABTRL},
+       {"BTRQ", LTYPE3, x86.ABTRQ},
+       {"BTRW", LTYPE3, x86.ABTRW},
+       {"BTSL", LTYPE3, x86.ABTSL},
+       {"BTSQ", LTYPE3, x86.ABTSQ},
+       {"BTSW", LTYPE3, x86.ABTSW},
+       {"BTW", LTYPE3, x86.ABTW},
+       {"BYTE", LTYPE2, x86.ABYTE},
+       {"CALL", LTYPEC, x86.ACALL},
+       {"CLC", LTYPE0, x86.ACLC},
+       {"CLD", LTYPE0, x86.ACLD},
+       {"CLI", LTYPE0, x86.ACLI},
+       {"CLTS", LTYPE0, x86.ACLTS},
+       {"CMC", LTYPE0, x86.ACMC},
+       {"CMPB", LTYPE4, x86.ACMPB},
+       {"CMPL", LTYPE4, x86.ACMPL},
+       {"CMPQ", LTYPE4, x86.ACMPQ},
+       {"CMPW", LTYPE4, x86.ACMPW},
+       {"CMPSB", LTYPE0, x86.ACMPSB},
+       {"CMPSL", LTYPE0, x86.ACMPSL},
+       {"CMPSQ", LTYPE0, x86.ACMPSQ},
+       {"CMPSW", LTYPE0, x86.ACMPSW},
+       {"CMPXCHG8B", LTYPE1, x86.ACMPXCHG8B},
+       {"CMPXCHGB", LTYPE3, x86.ACMPXCHGB}, /* LTYPE3? */
+       {"CMPXCHGL", LTYPE3, x86.ACMPXCHGL},
+       {"CMPXCHGQ", LTYPE3, x86.ACMPXCHGQ},
+       {"CMPXCHGW", LTYPE3, x86.ACMPXCHGW},
+       {"CPUID", LTYPE0, x86.ACPUID},
+       {"DAA", LTYPE0, x86.ADAA},
+       {"DAS", LTYPE0, x86.ADAS},
+       {"DATA", LTYPED, x86.ADATA},
+       {"DECB", LTYPE1, x86.ADECB},
+       {"DECL", LTYPE1, x86.ADECL},
+       {"DECQ", LTYPE1, x86.ADECQ},
+       {"DECW", LTYPE1, x86.ADECW},
+       {"DIVB", LTYPE2, x86.ADIVB},
+       {"DIVL", LTYPE2, x86.ADIVL},
+       {"DIVQ", LTYPE2, x86.ADIVQ},
+       {"DIVW", LTYPE2, x86.ADIVW},
+       {"EMMS", LTYPE0, x86.AEMMS},
+       {"END", LTYPE0, x86.AEND},
+       {"ENTER", LTYPE2, x86.AENTER},
+       {"GLOBL", LTYPEG, x86.AGLOBL},
+       {"HLT", LTYPE0, x86.AHLT},
+       {"IDIVB", LTYPE2, x86.AIDIVB},
+       {"IDIVL", LTYPE2, x86.AIDIVL},
+       {"IDIVQ", LTYPE2, x86.AIDIVQ},
+       {"IDIVW", LTYPE2, x86.AIDIVW},
+       {"IMULB", LTYPEI, x86.AIMULB},
+       {"IMULL", LTYPEI, x86.AIMULL},
+       {"IMULQ", LTYPEI, x86.AIMULQ},
+       {"IMUL3Q", LTYPEX, x86.AIMUL3Q},
+       {"IMULW", LTYPEI, x86.AIMULW},
+       {"INB", LTYPE0, x86.AINB},
+       {"INL", LTYPE0, x86.AINL},
+       {"INW", LTYPE0, x86.AINW},
+       {"INCB", LTYPE1, x86.AINCB},
+       {"INCL", LTYPE1, x86.AINCL},
+       {"INCQ", LTYPE1, x86.AINCQ},
+       {"INCW", LTYPE1, x86.AINCW},
+       {"INSB", LTYPE0, x86.AINSB},
+       {"INSL", LTYPE0, x86.AINSL},
+       {"INSW", LTYPE0, x86.AINSW},
+       {"INT", LTYPE2, x86.AINT},
+       {"INTO", LTYPE0, x86.AINTO},
+       {"INVD", LTYPE0, x86.AINVD},
+       {"INVLPG", LTYPE2, x86.AINVLPG},
+       {"IRETL", LTYPE0, x86.AIRETL},
+       {"IRETQ", LTYPE0, x86.AIRETQ},
+       {"IRETW", LTYPE0, x86.AIRETW},
+       {"JOS", LTYPER, x86.AJOS},  /* overflow set (OF = 1) */
+       {"JO", LTYPER, x86.AJOS},   /* alternate */
+       {"JOC", LTYPER, x86.AJOC},  /* overflow clear (OF = 0) */
+       {"JNO", LTYPER, x86.AJOC},  /* alternate */
+       {"JCS", LTYPER, x86.AJCS},  /* carry set (CF = 1) */
+       {"JB", LTYPER, x86.AJCS},   /* alternate */
+       {"JC", LTYPER, x86.AJCS},   /* alternate */
+       {"JNAE", LTYPER, x86.AJCS}, /* alternate */
+       {"JLO", LTYPER, x86.AJCS},  /* alternate */
+       {"JCC", LTYPER, x86.AJCC},  /* carry clear (CF = 0) */
+       {"JAE", LTYPER, x86.AJCC},  /* alternate */
+       {"JNB", LTYPER, x86.AJCC},  /* alternate */
+       {"JNC", LTYPER, x86.AJCC},  /* alternate */
+       {"JHS", LTYPER, x86.AJCC},  /* alternate */
+       {"JEQ", LTYPER, x86.AJEQ},  /* equal (ZF = 1) */
+       {"JE", LTYPER, x86.AJEQ},   /* alternate */
+       {"JZ", LTYPER, x86.AJEQ},   /* alternate */
+       {"JNE", LTYPER, x86.AJNE},  /* not equal (ZF = 0) */
+       {"JNZ", LTYPER, x86.AJNE},  /* alternate */
+       {"JLS", LTYPER, x86.AJLS},  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
+       {"JBE", LTYPER, x86.AJLS},  /* alternate */
+       {"JNA", LTYPER, x86.AJLS},  /* alternate */
+       {"JHI", LTYPER, x86.AJHI},  /* higher (unsigned) (CF = 0 && ZF = 0) */
+       {"JA", LTYPER, x86.AJHI},   /* alternate */
+       {"JNBE", LTYPER, x86.AJHI}, /* alternate */
+       {"JMI", LTYPER, x86.AJMI},  /* negative (minus) (SF = 1) */
+       {"JS", LTYPER, x86.AJMI},   /* alternate */
+       {"JPL", LTYPER, x86.AJPL},  /* non-negative (plus) (SF = 0) */
+       {"JNS", LTYPER, x86.AJPL},  /* alternate */
+       {"JPS", LTYPER, x86.AJPS},  /* parity set (PF = 1) */
+       {"JP", LTYPER, x86.AJPS},   /* alternate */
+       {"JPE", LTYPER, x86.AJPS},  /* alternate */
+       {"JPC", LTYPER, x86.AJPC},  /* parity clear (PF = 0) */
+       {"JNP", LTYPER, x86.AJPC},  /* alternate */
+       {"JPO", LTYPER, x86.AJPC},  /* alternate */
+       {"JLT", LTYPER, x86.AJLT},  /* less than (signed) (SF != OF) */
+       {"JL", LTYPER, x86.AJLT},   /* alternate */
+       {"JNGE", LTYPER, x86.AJLT}, /* alternate */
+       {"JGE", LTYPER, x86.AJGE},  /* greater than or equal (signed) (SF = OF) */
+       {"JNL", LTYPER, x86.AJGE},  /* alternate */
+       {"JLE", LTYPER, x86.AJLE},  /* less than or equal (signed) (ZF = 1 || SF != OF) */
+       {"JNG", LTYPER, x86.AJLE},  /* alternate */
+       {"JGT", LTYPER, x86.AJGT},  /* greater than (signed) (ZF = 0 && SF = OF) */
+       {"JG", LTYPER, x86.AJGT},   /* alternate */
+       {"JNLE", LTYPER, x86.AJGT}, /* alternate */
+       {"JCXZL", LTYPER, x86.AJCXZL},
+       {"JCXZQ", LTYPER, x86.AJCXZQ},
+       {"JMP", LTYPEC, x86.AJMP},
+       {"LAHF", LTYPE0, x86.ALAHF},
+       {"LARL", LTYPE3, x86.ALARL},
+       {"LARW", LTYPE3, x86.ALARW},
+       {"LEAL", LTYPE3, x86.ALEAL},
+       {"LEAQ", LTYPE3, x86.ALEAQ},
+       {"LEAW", LTYPE3, x86.ALEAW},
+       {"LEAVEL", LTYPE0, x86.ALEAVEL},
+       {"LEAVEQ", LTYPE0, x86.ALEAVEQ},
+       {"LEAVEW", LTYPE0, x86.ALEAVEW},
+       {"LFENCE", LTYPE0, x86.ALFENCE},
+       {"LOCK", LTYPE0, x86.ALOCK},
+       {"LODSB", LTYPE0, x86.ALODSB},
+       {"LODSL", LTYPE0, x86.ALODSL},
+       {"LODSQ", LTYPE0, x86.ALODSQ},
+       {"LODSW", LTYPE0, x86.ALODSW},
+       {"LONG", LTYPE2, x86.ALONG},
+       {"LOOP", LTYPER, x86.ALOOP},
+       {"LOOPEQ", LTYPER, x86.ALOOPEQ},
+       {"LOOPNE", LTYPER, x86.ALOOPNE},
+       {"LSLL", LTYPE3, x86.ALSLL},
+       {"LSLW", LTYPE3, x86.ALSLW},
+       {"MFENCE", LTYPE0, x86.AMFENCE},
+       {"MODE", LTYPE2, x86.AMODE},
+       {"MOVB", LTYPE3, x86.AMOVB},
+       {"MOVL", LTYPEM, x86.AMOVL},
+       {"MOVQ", LTYPEM, x86.AMOVQ},
+       {"MOVW", LTYPEM, x86.AMOVW},
+       {"MOVBLSX", LTYPE3, x86.AMOVBLSX},
+       {"MOVBLZX", LTYPE3, x86.AMOVBLZX},
+       {"MOVBQSX", LTYPE3, x86.AMOVBQSX},
+       {"MOVBQZX", LTYPE3, x86.AMOVBQZX},
+       {"MOVBWSX", LTYPE3, x86.AMOVBWSX},
+       {"MOVBWZX", LTYPE3, x86.AMOVBWZX},
+       {"MOVLQSX", LTYPE3, x86.AMOVLQSX},
+       {"MOVLQZX", LTYPE3, x86.AMOVLQZX},
+       {"MOVNTIL", LTYPE3, x86.AMOVNTIL},
+       {"MOVNTIQ", LTYPE3, x86.AMOVNTIQ},
+       {"MOVQL", LTYPE3, x86.AMOVQL},
+       {"MOVWLSX", LTYPE3, x86.AMOVWLSX},
+       {"MOVWLZX", LTYPE3, x86.AMOVWLZX},
+       {"MOVWQSX", LTYPE3, x86.AMOVWQSX},
+       {"MOVWQZX", LTYPE3, x86.AMOVWQZX},
+       {"MOVSB", LTYPE0, x86.AMOVSB},
+       {"MOVSL", LTYPE0, x86.AMOVSL},
+       {"MOVSQ", LTYPE0, x86.AMOVSQ},
+       {"MOVSW", LTYPE0, x86.AMOVSW},
+       {"MULB", LTYPE2, x86.AMULB},
+       {"MULL", LTYPE2, x86.AMULL},
+       {"MULQ", LTYPE2, x86.AMULQ},
+       {"MULW", LTYPE2, x86.AMULW},
+       {"NEGB", LTYPE1, x86.ANEGB},
+       {"NEGL", LTYPE1, x86.ANEGL},
+       {"NEGQ", LTYPE1, x86.ANEGQ},
+       {"NEGW", LTYPE1, x86.ANEGW},
+       {"NOP", LTYPEN, x86.ANOP},
+       {"NOTB", LTYPE1, x86.ANOTB},
+       {"NOTL", LTYPE1, x86.ANOTL},
+       {"NOTQ", LTYPE1, x86.ANOTQ},
+       {"NOTW", LTYPE1, x86.ANOTW},
+       {"ORB", LTYPE3, x86.AORB},
+       {"ORL", LTYPE3, x86.AORL},
+       {"ORQ", LTYPE3, x86.AORQ},
+       {"ORW", LTYPE3, x86.AORW},
+       {"OUTB", LTYPE0, x86.AOUTB},
+       {"OUTL", LTYPE0, x86.AOUTL},
+       {"OUTW", LTYPE0, x86.AOUTW},
+       {"OUTSB", LTYPE0, x86.AOUTSB},
+       {"OUTSL", LTYPE0, x86.AOUTSL},
+       {"OUTSW", LTYPE0, x86.AOUTSW},
+       {"PAUSE", LTYPEN, x86.APAUSE},
+       {"POPAL", LTYPE0, x86.APOPAL},
+       {"POPAW", LTYPE0, x86.APOPAW},
+       {"POPFL", LTYPE0, x86.APOPFL},
+       {"POPFQ", LTYPE0, x86.APOPFQ},
+       {"POPFW", LTYPE0, x86.APOPFW},
+       {"POPL", LTYPE1, x86.APOPL},
+       {"POPQ", LTYPE1, x86.APOPQ},
+       {"POPW", LTYPE1, x86.APOPW},
+       {"PUSHAL", LTYPE0, x86.APUSHAL},
+       {"PUSHAW", LTYPE0, x86.APUSHAW},
+       {"PUSHFL", LTYPE0, x86.APUSHFL},
+       {"PUSHFQ", LTYPE0, x86.APUSHFQ},
+       {"PUSHFW", LTYPE0, x86.APUSHFW},
+       {"PUSHL", LTYPE2, x86.APUSHL},
+       {"PUSHQ", LTYPE2, x86.APUSHQ},
+       {"PUSHW", LTYPE2, x86.APUSHW},
+       {"RCLB", LTYPE3, x86.ARCLB},
+       {"RCLL", LTYPE3, x86.ARCLL},
+       {"RCLQ", LTYPE3, x86.ARCLQ},
+       {"RCLW", LTYPE3, x86.ARCLW},
+       {"RCRB", LTYPE3, x86.ARCRB},
+       {"RCRL", LTYPE3, x86.ARCRL},
+       {"RCRQ", LTYPE3, x86.ARCRQ},
+       {"RCRW", LTYPE3, x86.ARCRW},
+       {"RDMSR", LTYPE0, x86.ARDMSR},
+       {"RDPMC", LTYPE0, x86.ARDPMC},
+       {"RDTSC", LTYPE0, x86.ARDTSC},
+       {"REP", LTYPE0, x86.AREP},
+       {"REPN", LTYPE0, x86.AREPN},
+       {"RET", LTYPE0, x86.ARET},
+       {"RETFL", LTYPERT, x86.ARETFL},
+       {"RETFW", LTYPERT, x86.ARETFW},
+       {"RETFQ", LTYPERT, x86.ARETFQ},
+       {"ROLB", LTYPE3, x86.AROLB},
+       {"ROLL", LTYPE3, x86.AROLL},
+       {"ROLQ", LTYPE3, x86.AROLQ},
+       {"ROLW", LTYPE3, x86.AROLW},
+       {"RORB", LTYPE3, x86.ARORB},
+       {"RORL", LTYPE3, x86.ARORL},
+       {"RORQ", LTYPE3, x86.ARORQ},
+       {"RORW", LTYPE3, x86.ARORW},
+       {"RSM", LTYPE0, x86.ARSM},
+       {"SAHF", LTYPE0, x86.ASAHF},
+       {"SALB", LTYPE3, x86.ASALB},
+       {"SALL", LTYPE3, x86.ASALL},
+       {"SALQ", LTYPE3, x86.ASALQ},
+       {"SALW", LTYPE3, x86.ASALW},
+       {"SARB", LTYPE3, x86.ASARB},
+       {"SARL", LTYPE3, x86.ASARL},
+       {"SARQ", LTYPE3, x86.ASARQ},
+       {"SARW", LTYPE3, x86.ASARW},
+       {"SBBB", LTYPE3, x86.ASBBB},
+       {"SBBL", LTYPE3, x86.ASBBL},
+       {"SBBQ", LTYPE3, x86.ASBBQ},
+       {"SBBW", LTYPE3, x86.ASBBW},
+       {"SCASB", LTYPE0, x86.ASCASB},
+       {"SCASL", LTYPE0, x86.ASCASL},
+       {"SCASQ", LTYPE0, x86.ASCASQ},
+       {"SCASW", LTYPE0, x86.ASCASW},
+       {"SETCC", LTYPE1, x86.ASETCC}, /* see JCC etc above for condition codes */
+       {"SETCS", LTYPE1, x86.ASETCS},
+       {"SETEQ", LTYPE1, x86.ASETEQ},
+       {"SETGE", LTYPE1, x86.ASETGE},
+       {"SETGT", LTYPE1, x86.ASETGT},
+       {"SETHI", LTYPE1, x86.ASETHI},
+       {"SETLE", LTYPE1, x86.ASETLE},
+       {"SETLS", LTYPE1, x86.ASETLS},
+       {"SETLT", LTYPE1, x86.ASETLT},
+       {"SETMI", LTYPE1, x86.ASETMI},
+       {"SETNE", LTYPE1, x86.ASETNE},
+       {"SETOC", LTYPE1, x86.ASETOC},
+       {"SETOS", LTYPE1, x86.ASETOS},
+       {"SETPC", LTYPE1, x86.ASETPC},
+       {"SETPL", LTYPE1, x86.ASETPL},
+       {"SETPS", LTYPE1, x86.ASETPS},
+       {"SFENCE", LTYPE0, x86.ASFENCE},
+       {"CDQ", LTYPE0, x86.ACDQ},
+       {"CWD", LTYPE0, x86.ACWD},
+       {"CQO", LTYPE0, x86.ACQO},
+       {"SHLB", LTYPE3, x86.ASHLB},
+       {"SHLL", LTYPES, x86.ASHLL},
+       {"SHLQ", LTYPES, x86.ASHLQ},
+       {"SHLW", LTYPES, x86.ASHLW},
+       {"SHRB", LTYPE3, x86.ASHRB},
+       {"SHRL", LTYPES, x86.ASHRL},
+       {"SHRQ", LTYPES, x86.ASHRQ},
+       {"SHRW", LTYPES, x86.ASHRW},
+       {"STC", LTYPE0, x86.ASTC},
+       {"STD", LTYPE0, x86.ASTD},
+       {"STI", LTYPE0, x86.ASTI},
+       {"STOSB", LTYPE0, x86.ASTOSB},
+       {"STOSL", LTYPE0, x86.ASTOSL},
+       {"STOSQ", LTYPE0, x86.ASTOSQ},
+       {"STOSW", LTYPE0, x86.ASTOSW},
+       {"SUBB", LTYPE3, x86.ASUBB},
+       {"SUBL", LTYPE3, x86.ASUBL},
+       {"SUBQ", LTYPE3, x86.ASUBQ},
+       {"SUBW", LTYPE3, x86.ASUBW},
+       {"SYSCALL", LTYPE0, x86.ASYSCALL},
+       {"SYSRET", LTYPE0, x86.ASYSRET},
+       {"SWAPGS", LTYPE0, x86.ASWAPGS},
+       {"TESTB", LTYPE3, x86.ATESTB},
+       {"TESTL", LTYPE3, x86.ATESTL},
+       {"TESTQ", LTYPE3, x86.ATESTQ},
+       {"TESTW", LTYPE3, x86.ATESTW},
+       {"TEXT", LTYPET, x86.ATEXT},
+       {"VERR", LTYPE2, x86.AVERR},
+       {"VERW", LTYPE2, x86.AVERW},
+       {"QUAD", LTYPE2, x86.AQUAD},
+       {"WAIT", LTYPE0, x86.AWAIT},
+       {"WBINVD", LTYPE0, x86.AWBINVD},
+       {"WRMSR", LTYPE0, x86.AWRMSR},
+       {"WORD", LTYPE2, x86.AWORD},
+       {"XADDB", LTYPE3, x86.AXADDB},
+       {"XADDL", LTYPE3, x86.AXADDL},
+       {"XADDQ", LTYPE3, x86.AXADDQ},
+       {"XADDW", LTYPE3, x86.AXADDW},
+       {"XCHGB", LTYPE3, x86.AXCHGB},
+       {"XCHGL", LTYPE3, x86.AXCHGL},
+       {"XCHGQ", LTYPE3, x86.AXCHGQ},
+       {"XCHGW", LTYPE3, x86.AXCHGW},
+       {"XLAT", LTYPE2, x86.AXLAT},
+       {"XORB", LTYPE3, x86.AXORB},
+       {"XORL", LTYPE3, x86.AXORL},
+       {"XORQ", LTYPE3, x86.AXORQ},
+       {"XORW", LTYPE3, x86.AXORW},
+       {"CMOVLCC", LTYPE3, x86.ACMOVLCC},
+       {"CMOVLCS", LTYPE3, x86.ACMOVLCS},
+       {"CMOVLEQ", LTYPE3, x86.ACMOVLEQ},
+       {"CMOVLGE", LTYPE3, x86.ACMOVLGE},
+       {"CMOVLGT", LTYPE3, x86.ACMOVLGT},
+       {"CMOVLHI", LTYPE3, x86.ACMOVLHI},
+       {"CMOVLLE", LTYPE3, x86.ACMOVLLE},
+       {"CMOVLLS", LTYPE3, x86.ACMOVLLS},
+       {"CMOVLLT", LTYPE3, x86.ACMOVLLT},
+       {"CMOVLMI", LTYPE3, x86.ACMOVLMI},
+       {"CMOVLNE", LTYPE3, x86.ACMOVLNE},
+       {"CMOVLOC", LTYPE3, x86.ACMOVLOC},
+       {"CMOVLOS", LTYPE3, x86.ACMOVLOS},
+       {"CMOVLPC", LTYPE3, x86.ACMOVLPC},
+       {"CMOVLPL", LTYPE3, x86.ACMOVLPL},
+       {"CMOVLPS", LTYPE3, x86.ACMOVLPS},
+       {"CMOVQCC", LTYPE3, x86.ACMOVQCC},
+       {"CMOVQCS", LTYPE3, x86.ACMOVQCS},
+       {"CMOVQEQ", LTYPE3, x86.ACMOVQEQ},
+       {"CMOVQGE", LTYPE3, x86.ACMOVQGE},
+       {"CMOVQGT", LTYPE3, x86.ACMOVQGT},
+       {"CMOVQHI", LTYPE3, x86.ACMOVQHI},
+       {"CMOVQLE", LTYPE3, x86.ACMOVQLE},
+       {"CMOVQLS", LTYPE3, x86.ACMOVQLS},
+       {"CMOVQLT", LTYPE3, x86.ACMOVQLT},
+       {"CMOVQMI", LTYPE3, x86.ACMOVQMI},
+       {"CMOVQNE", LTYPE3, x86.ACMOVQNE},
+       {"CMOVQOC", LTYPE3, x86.ACMOVQOC},
+       {"CMOVQOS", LTYPE3, x86.ACMOVQOS},
+       {"CMOVQPC", LTYPE3, x86.ACMOVQPC},
+       {"CMOVQPL", LTYPE3, x86.ACMOVQPL},
+       {"CMOVQPS", LTYPE3, x86.ACMOVQPS},
+       {"CMOVWCC", LTYPE3, x86.ACMOVWCC},
+       {"CMOVWCS", LTYPE3, x86.ACMOVWCS},
+       {"CMOVWEQ", LTYPE3, x86.ACMOVWEQ},
+       {"CMOVWGE", LTYPE3, x86.ACMOVWGE},
+       {"CMOVWGT", LTYPE3, x86.ACMOVWGT},
+       {"CMOVWHI", LTYPE3, x86.ACMOVWHI},
+       {"CMOVWLE", LTYPE3, x86.ACMOVWLE},
+       {"CMOVWLS", LTYPE3, x86.ACMOVWLS},
+       {"CMOVWLT", LTYPE3, x86.ACMOVWLT},
+       {"CMOVWMI", LTYPE3, x86.ACMOVWMI},
+       {"CMOVWNE", LTYPE3, x86.ACMOVWNE},
+       {"CMOVWOC", LTYPE3, x86.ACMOVWOC},
+       {"CMOVWOS", LTYPE3, x86.ACMOVWOS},
+       {"CMOVWPC", LTYPE3, x86.ACMOVWPC},
+       {"CMOVWPL", LTYPE3, x86.ACMOVWPL},
+       {"CMOVWPS", LTYPE3, x86.ACMOVWPS},
+       {"FMOVB", LTYPE3, x86.AFMOVB},
+       {"FMOVBP", LTYPE3, x86.AFMOVBP},
+       {"FMOVD", LTYPE3, x86.AFMOVD},
+       {"FMOVDP", LTYPE3, x86.AFMOVDP},
+       {"FMOVF", LTYPE3, x86.AFMOVF},
+       {"FMOVFP", LTYPE3, x86.AFMOVFP},
+       {"FMOVL", LTYPE3, x86.AFMOVL},
+       {"FMOVLP", LTYPE3, x86.AFMOVLP},
+       {"FMOVV", LTYPE3, x86.AFMOVV},
+       {"FMOVVP", LTYPE3, x86.AFMOVVP},
+       {"FMOVW", LTYPE3, x86.AFMOVW},
+       {"FMOVWP", LTYPE3, x86.AFMOVWP},
+       {"FMOVX", LTYPE3, x86.AFMOVX},
+       {"FMOVXP", LTYPE3, x86.AFMOVXP},
+       {"FCOMB", LTYPE3, x86.AFCOMB},
+       {"FCOMBP", LTYPE3, x86.AFCOMBP},
+       {"FCOMD", LTYPE3, x86.AFCOMD},
+       {"FCOMDP", LTYPE3, x86.AFCOMDP},
+       {"FCOMDPP", LTYPE3, x86.AFCOMDPP},
+       {"FCOMF", LTYPE3, x86.AFCOMF},
+       {"FCOMFP", LTYPE3, x86.AFCOMFP},
+       {"FCOML", LTYPE3, x86.AFCOML},
+       {"FCOMLP", LTYPE3, x86.AFCOMLP},
+       {"FCOMW", LTYPE3, x86.AFCOMW},
+       {"FCOMWP", LTYPE3, x86.AFCOMWP},
+       {"FUCOM", LTYPE3, x86.AFUCOM},
+       {"FUCOMP", LTYPE3, x86.AFUCOMP},
+       {"FUCOMPP", LTYPE3, x86.AFUCOMPP},
+       {"FADDW", LTYPE3, x86.AFADDW},
+       {"FADDL", LTYPE3, x86.AFADDL},
+       {"FADDF", LTYPE3, x86.AFADDF},
+       {"FADDD", LTYPE3, x86.AFADDD},
+       {"FADDDP", LTYPE3, x86.AFADDDP},
+       {"FSUBDP", LTYPE3, x86.AFSUBDP},
+       {"FSUBW", LTYPE3, x86.AFSUBW},
+       {"FSUBL", LTYPE3, x86.AFSUBL},
+       {"FSUBF", LTYPE3, x86.AFSUBF},
+       {"FSUBD", LTYPE3, x86.AFSUBD},
+       {"FSUBRDP", LTYPE3, x86.AFSUBRDP},
+       {"FSUBRW", LTYPE3, x86.AFSUBRW},
+       {"FSUBRL", LTYPE3, x86.AFSUBRL},
+       {"FSUBRF", LTYPE3, x86.AFSUBRF},
+       {"FSUBRD", LTYPE3, x86.AFSUBRD},
+       {"FMULDP", LTYPE3, x86.AFMULDP},
+       {"FMULW", LTYPE3, x86.AFMULW},
+       {"FMULL", LTYPE3, x86.AFMULL},
+       {"FMULF", LTYPE3, x86.AFMULF},
+       {"FMULD", LTYPE3, x86.AFMULD},
+       {"FDIVDP", LTYPE3, x86.AFDIVDP},
+       {"FDIVW", LTYPE3, x86.AFDIVW},
+       {"FDIVL", LTYPE3, x86.AFDIVL},
+       {"FDIVF", LTYPE3, x86.AFDIVF},
+       {"FDIVD", LTYPE3, x86.AFDIVD},
+       {"FDIVRDP", LTYPE3, x86.AFDIVRDP},
+       {"FDIVRW", LTYPE3, x86.AFDIVRW},
+       {"FDIVRL", LTYPE3, x86.AFDIVRL},
+       {"FDIVRF", LTYPE3, x86.AFDIVRF},
+       {"FDIVRD", LTYPE3, x86.AFDIVRD},
+       {"FXCHD", LTYPE3, x86.AFXCHD},
+       {"FFREE", LTYPE1, x86.AFFREE},
+       {"FLDCW", LTYPE2, x86.AFLDCW},
+       {"FLDENV", LTYPE1, x86.AFLDENV},
+       {"FRSTOR", LTYPE2, x86.AFRSTOR},
+       {"FSAVE", LTYPE1, x86.AFSAVE},
+       {"FSTCW", LTYPE1, x86.AFSTCW},
+       {"FSTENV", LTYPE1, x86.AFSTENV},
+       {"FSTSW", LTYPE1, x86.AFSTSW},
+       {"F2XM1", LTYPE0, x86.AF2XM1},
+       {"FABS", LTYPE0, x86.AFABS},
+       {"FCHS", LTYPE0, x86.AFCHS},
+       {"FCLEX", LTYPE0, x86.AFCLEX},
+       {"FCOS", LTYPE0, x86.AFCOS},
+       {"FDECSTP", LTYPE0, x86.AFDECSTP},
+       {"FINCSTP", LTYPE0, x86.AFINCSTP},
+       {"FINIT", LTYPE0, x86.AFINIT},
+       {"FLD1", LTYPE0, x86.AFLD1},
+       {"FLDL2E", LTYPE0, x86.AFLDL2E},
+       {"FLDL2T", LTYPE0, x86.AFLDL2T},
+       {"FLDLG2", LTYPE0, x86.AFLDLG2},
+       {"FLDLN2", LTYPE0, x86.AFLDLN2},
+       {"FLDPI", LTYPE0, x86.AFLDPI},
+       {"FLDZ", LTYPE0, x86.AFLDZ},
+       {"FNOP", LTYPE0, x86.AFNOP},
+       {"FPATAN", LTYPE0, x86.AFPATAN},
+       {"FPREM", LTYPE0, x86.AFPREM},
+       {"FPREM1", LTYPE0, x86.AFPREM1},
+       {"FPTAN", LTYPE0, x86.AFPTAN},
+       {"FRNDINT", LTYPE0, x86.AFRNDINT},
+       {"FSCALE", LTYPE0, x86.AFSCALE},
+       {"FSIN", LTYPE0, x86.AFSIN},
+       {"FSINCOS", LTYPE0, x86.AFSINCOS},
+       {"FSQRT", LTYPE0, x86.AFSQRT},
+       {"FTST", LTYPE0, x86.AFTST},
+       {"FXAM", LTYPE0, x86.AFXAM},
+       {"FXTRACT", LTYPE0, x86.AFXTRACT},
+       {"FYL2X", LTYPE0, x86.AFYL2X},
+       {"FYL2XP1", LTYPE0, x86.AFYL2XP1},
+       {"ADDPD", LTYPE3, x86.AADDPD},
+       {"ADDPS", LTYPE3, x86.AADDPS},
+       {"ADDSD", LTYPE3, x86.AADDSD},
+       {"ADDSS", LTYPE3, x86.AADDSS},
+       {"ANDNPD", LTYPE3, x86.AANDNPD},
+       {"ANDNPS", LTYPE3, x86.AANDNPS},
+       {"ANDPD", LTYPE3, x86.AANDPD},
+       {"ANDPS", LTYPE3, x86.AANDPS},
+       {"CMPPD", LTYPEXC, x86.ACMPPD},
+       {"CMPPS", LTYPEXC, x86.ACMPPS},
+       {"CMPSD", LTYPEXC, x86.ACMPSD},
+       {"CMPSS", LTYPEXC, x86.ACMPSS},
+       {"COMISD", LTYPE3, x86.ACOMISD},
+       {"COMISS", LTYPE3, x86.ACOMISS},
+       {"CVTPL2PD", LTYPE3, x86.ACVTPL2PD},
+       {"CVTPL2PS", LTYPE3, x86.ACVTPL2PS},
+       {"CVTPD2PL", LTYPE3, x86.ACVTPD2PL},
+       {"CVTPD2PS", LTYPE3, x86.ACVTPD2PS},
+       {"CVTPS2PL", LTYPE3, x86.ACVTPS2PL},
+       {"PF2IW", LTYPE3, x86.APF2IW},
+       {"PF2IL", LTYPE3, x86.APF2IL},
+       {"PF2ID", LTYPE3, x86.APF2IL}, /* syn */
+       {"PI2FL", LTYPE3, x86.API2FL},
+       {"PI2FD", LTYPE3, x86.API2FL}, /* syn */
+       {"PI2FW", LTYPE3, x86.API2FW},
+       {"CVTPS2PD", LTYPE3, x86.ACVTPS2PD},
+       {"CVTSD2SL", LTYPE3, x86.ACVTSD2SL},
+       {"CVTSD2SQ", LTYPE3, x86.ACVTSD2SQ},
+       {"CVTSD2SS", LTYPE3, x86.ACVTSD2SS},
+       {"CVTSL2SD", LTYPE3, x86.ACVTSL2SD},
+       {"CVTSQ2SD", LTYPE3, x86.ACVTSQ2SD},
+       {"CVTSL2SS", LTYPE3, x86.ACVTSL2SS},
+       {"CVTSQ2SS", LTYPE3, x86.ACVTSQ2SS},
+       {"CVTSS2SD", LTYPE3, x86.ACVTSS2SD},
+       {"CVTSS2SL", LTYPE3, x86.ACVTSS2SL},
+       {"CVTSS2SQ", LTYPE3, x86.ACVTSS2SQ},
+       {"CVTTPD2PL", LTYPE3, x86.ACVTTPD2PL},
+       {"CVTTPS2PL", LTYPE3, x86.ACVTTPS2PL},
+       {"CVTTSD2SL", LTYPE3, x86.ACVTTSD2SL},
+       {"CVTTSD2SQ", LTYPE3, x86.ACVTTSD2SQ},
+       {"CVTTSS2SL", LTYPE3, x86.ACVTTSS2SL},
+       {"CVTTSS2SQ", LTYPE3, x86.ACVTTSS2SQ},
+       {"DIVPD", LTYPE3, x86.ADIVPD},
+       {"DIVPS", LTYPE3, x86.ADIVPS},
+       {"DIVSD", LTYPE3, x86.ADIVSD},
+       {"DIVSS", LTYPE3, x86.ADIVSS},
+       {"FXRSTOR", LTYPE2, x86.AFXRSTOR},
+       {"FXRSTOR64", LTYPE2, x86.AFXRSTOR64},
+       {"FXSAVE", LTYPE1, x86.AFXSAVE},
+       {"FXSAVE64", LTYPE1, x86.AFXSAVE64},
+       {"LDMXCSR", LTYPE2, x86.ALDMXCSR},
+       {"MASKMOVOU", LTYPE3, x86.AMASKMOVOU},
+       {"MASKMOVDQU", LTYPE3, x86.AMASKMOVOU}, /* syn */
+       {"MASKMOVQ", LTYPE3, x86.AMASKMOVQ},
+       {"MAXPD", LTYPE3, x86.AMAXPD},
+       {"MAXPS", LTYPE3, x86.AMAXPS},
+       {"MAXSD", LTYPE3, x86.AMAXSD},
+       {"MAXSS", LTYPE3, x86.AMAXSS},
+       {"MINPD", LTYPE3, x86.AMINPD},
+       {"MINPS", LTYPE3, x86.AMINPS},
+       {"MINSD", LTYPE3, x86.AMINSD},
+       {"MINSS", LTYPE3, x86.AMINSS},
+       {"MOVAPD", LTYPE3, x86.AMOVAPD},
+       {"MOVAPS", LTYPE3, x86.AMOVAPS},
+       {"MOVD", LTYPE3, x86.AMOVQ},    /* syn */
+       {"MOVDQ2Q", LTYPE3, x86.AMOVQ}, /* syn */
+       {"MOVO", LTYPE3, x86.AMOVO},
+       {"MOVOA", LTYPE3, x86.AMOVO}, /* syn */
+       {"MOVOU", LTYPE3, x86.AMOVOU},
+       {"MOVHLPS", LTYPE3, x86.AMOVHLPS},
+       {"MOVHPD", LTYPE3, x86.AMOVHPD},
+       {"MOVHPS", LTYPE3, x86.AMOVHPS},
+       {"MOVLHPS", LTYPE3, x86.AMOVLHPS},
+       {"MOVLPD", LTYPE3, x86.AMOVLPD},
+       {"MOVLPS", LTYPE3, x86.AMOVLPS},
+       {"MOVMSKPD", LTYPE3, x86.AMOVMSKPD},
+       {"MOVMSKPS", LTYPE3, x86.AMOVMSKPS},
+       {"MOVNTO", LTYPE3, x86.AMOVNTO},
+       {"MOVNTDQ", LTYPE3, x86.AMOVNTO}, /* syn */
+       {"MOVNTPD", LTYPE3, x86.AMOVNTPD},
+       {"MOVNTPS", LTYPE3, x86.AMOVNTPS},
+       {"MOVNTQ", LTYPE3, x86.AMOVNTQ},
+       {"MOVQOZX", LTYPE3, x86.AMOVQOZX},
+       {"MOVSD", LTYPE3, x86.AMOVSD},
+       {"MOVSS", LTYPE3, x86.AMOVSS},
+       {"MOVUPD", LTYPE3, x86.AMOVUPD},
+       {"MOVUPS", LTYPE3, x86.AMOVUPS},
+       {"MULPD", LTYPE3, x86.AMULPD},
+       {"MULPS", LTYPE3, x86.AMULPS},
+       {"MULSD", LTYPE3, x86.AMULSD},
+       {"MULSS", LTYPE3, x86.AMULSS},
+       {"ORPD", LTYPE3, x86.AORPD},
+       {"ORPS", LTYPE3, x86.AORPS},
+       {"PACKSSLW", LTYPE3, x86.APACKSSLW},
+       {"PACKSSWB", LTYPE3, x86.APACKSSWB},
+       {"PACKUSWB", LTYPE3, x86.APACKUSWB},
+       {"PADDB", LTYPE3, x86.APADDB},
+       {"PADDL", LTYPE3, x86.APADDL},
+       {"PADDQ", LTYPE3, x86.APADDQ},
+       {"PADDSB", LTYPE3, x86.APADDSB},
+       {"PADDSW", LTYPE3, x86.APADDSW},
+       {"PADDUSB", LTYPE3, x86.APADDUSB},
+       {"PADDUSW", LTYPE3, x86.APADDUSW},
+       {"PADDW", LTYPE3, x86.APADDW},
+       {"PAND", LTYPE3, x86.APAND},
+       {"PANDB", LTYPE3, x86.APANDB},
+       {"PANDL", LTYPE3, x86.APANDL},
+       {"PANDSB", LTYPE3, x86.APANDSB},
+       {"PANDSW", LTYPE3, x86.APANDSW},
+       {"PANDUSB", LTYPE3, x86.APANDUSB},
+       {"PANDUSW", LTYPE3, x86.APANDUSW},
+       {"PANDW", LTYPE3, x86.APANDW},
+       {"PANDN", LTYPE3, x86.APANDN},
+       {"PAVGB", LTYPE3, x86.APAVGB},
+       {"PAVGW", LTYPE3, x86.APAVGW},
+       {"PCMPEQB", LTYPE3, x86.APCMPEQB},
+       {"PCMPEQL", LTYPE3, x86.APCMPEQL},
+       {"PCMPEQW", LTYPE3, x86.APCMPEQW},
+       {"PCMPGTB", LTYPE3, x86.APCMPGTB},
+       {"PCMPGTL", LTYPE3, x86.APCMPGTL},
+       {"PCMPGTW", LTYPE3, x86.APCMPGTW},
+       {"PEXTRW", LTYPEX, x86.APEXTRW},
+       {"PINSRW", LTYPEX, x86.APINSRW},
+       {"PINSRD", LTYPEX, x86.APINSRD},
+       {"PINSRQ", LTYPEX, x86.APINSRQ},
+       {"PMADDWL", LTYPE3, x86.APMADDWL},
+       {"PMAXSW", LTYPE3, x86.APMAXSW},
+       {"PMAXUB", LTYPE3, x86.APMAXUB},
+       {"PMINSW", LTYPE3, x86.APMINSW},
+       {"PMINUB", LTYPE3, x86.APMINUB},
+       {"PMOVMSKB", LTYPE3, x86.APMOVMSKB},
+       {"PMULHRW", LTYPE3, x86.APMULHRW},
+       {"PMULHUW", LTYPE3, x86.APMULHUW},
+       {"PMULHW", LTYPE3, x86.APMULHW},
+       {"PMULLW", LTYPE3, x86.APMULLW},
+       {"PMULULQ", LTYPE3, x86.APMULULQ},
+       {"POR", LTYPE3, x86.APOR},
+       {"PSADBW", LTYPE3, x86.APSADBW},
+       {"PSHUFHW", LTYPEX, x86.APSHUFHW},
+       {"PSHUFL", LTYPEX, x86.APSHUFL},
+       {"PSHUFLW", LTYPEX, x86.APSHUFLW},
+       {"PSHUFW", LTYPEX, x86.APSHUFW},
+       {"PSHUFB", LTYPEM, x86.APSHUFB},
+       {"PSLLO", LTYPE3, x86.APSLLO},
+       {"PSLLDQ", LTYPE3, x86.APSLLO}, /* syn */
+       {"PSLLL", LTYPE3, x86.APSLLL},
+       {"PSLLQ", LTYPE3, x86.APSLLQ},
+       {"PSLLW", LTYPE3, x86.APSLLW},
+       {"PSRAL", LTYPE3, x86.APSRAL},
+       {"PSRAW", LTYPE3, x86.APSRAW},
+       {"PSRLO", LTYPE3, x86.APSRLO},
+       {"PSRLDQ", LTYPE3, x86.APSRLO}, /* syn */
+       {"PSRLL", LTYPE3, x86.APSRLL},
+       {"PSRLQ", LTYPE3, x86.APSRLQ},
+       {"PSRLW", LTYPE3, x86.APSRLW},
+       {"PSUBB", LTYPE3, x86.APSUBB},
+       {"PSUBL", LTYPE3, x86.APSUBL},
+       {"PSUBQ", LTYPE3, x86.APSUBQ},
+       {"PSUBSB", LTYPE3, x86.APSUBSB},
+       {"PSUBSW", LTYPE3, x86.APSUBSW},
+       {"PSUBUSB", LTYPE3, x86.APSUBUSB},
+       {"PSUBUSW", LTYPE3, x86.APSUBUSW},
+       {"PSUBW", LTYPE3, x86.APSUBW},
+       {"PUNPCKHBW", LTYPE3, x86.APUNPCKHBW},
+       {"PUNPCKHLQ", LTYPE3, x86.APUNPCKHLQ},
+       {"PUNPCKHQDQ", LTYPE3, x86.APUNPCKHQDQ},
+       {"PUNPCKHWL", LTYPE3, x86.APUNPCKHWL},
+       {"PUNPCKLBW", LTYPE3, x86.APUNPCKLBW},
+       {"PUNPCKLLQ", LTYPE3, x86.APUNPCKLLQ},
+       {"PUNPCKLQDQ", LTYPE3, x86.APUNPCKLQDQ},
+       {"PUNPCKLWL", LTYPE3, x86.APUNPCKLWL},
+       {"PXOR", LTYPE3, x86.APXOR},
+       {"RCPPS", LTYPE3, x86.ARCPPS},
+       {"RCPSS", LTYPE3, x86.ARCPSS},
+       {"RSQRTPS", LTYPE3, x86.ARSQRTPS},
+       {"RSQRTSS", LTYPE3, x86.ARSQRTSS},
+       {"SHUFPD", LTYPEX, x86.ASHUFPD},
+       {"SHUFPS", LTYPEX, x86.ASHUFPS},
+       {"SQRTPD", LTYPE3, x86.ASQRTPD},
+       {"SQRTPS", LTYPE3, x86.ASQRTPS},
+       {"SQRTSD", LTYPE3, x86.ASQRTSD},
+       {"SQRTSS", LTYPE3, x86.ASQRTSS},
+       {"STMXCSR", LTYPE1, x86.ASTMXCSR},
+       {"SUBPD", LTYPE3, x86.ASUBPD},
+       {"SUBPS", LTYPE3, x86.ASUBPS},
+       {"SUBSD", LTYPE3, x86.ASUBSD},
+       {"SUBSS", LTYPE3, x86.ASUBSS},
+       {"UCOMISD", LTYPE3, x86.AUCOMISD},
+       {"UCOMISS", LTYPE3, x86.AUCOMISS},
+       {"UNPCKHPD", LTYPE3, x86.AUNPCKHPD},
+       {"UNPCKHPS", LTYPE3, x86.AUNPCKHPS},
+       {"UNPCKLPD", LTYPE3, x86.AUNPCKLPD},
+       {"UNPCKLPS", LTYPE3, x86.AUNPCKLPS},
+       {"XORPD", LTYPE3, x86.AXORPD},
+       {"XORPS", LTYPE3, x86.AXORPS},
+       {"CRC32B", LTYPE4, x86.ACRC32B},
+       {"CRC32Q", LTYPE4, x86.ACRC32Q},
+       {"PREFETCHT0", LTYPE2, x86.APREFETCHT0},
+       {"PREFETCHT1", LTYPE2, x86.APREFETCHT1},
+       {"PREFETCHT2", LTYPE2, x86.APREFETCHT2},
+       {"PREFETCHNTA", LTYPE2, x86.APREFETCHNTA},
+       {"UNDEF", LTYPE0, x86.AUNDEF},
+       {"AESENC", LTYPE3, x86.AAESENC},
+       {"AESENCLAST", LTYPE3, x86.AAESENCLAST},
+       {"AESDEC", LTYPE3, x86.AAESDEC},
+       {"AESDECLAST", LTYPE3, x86.AAESDECLAST},
+       {"AESIMC", LTYPE3, x86.AAESIMC},
+       {"AESKEYGENASSIST", LTYPEX, x86.AAESKEYGENASSIST},
+       {"PSHUFD", LTYPEX, x86.APSHUFD},
+       {"USEFIELD", LTYPEN, x86.AUSEFIELD},
+       {"PCLMULQDQ", LTYPEX, x86.APCLMULQDQ},
+       {"PCDATA", LTYPEPC, x86.APCDATA},
+       {"FUNCDATA", LTYPEF, x86.AFUNCDATA},
+}
+
+func cinit() {
+       nullgen.Type = x86.D_NONE
+       nullgen.Index = x86.D_NONE
+}
+
+func checkscale(scale int8) {
+       switch scale {
+       case 1,
+               2,
+               4,
+               8:
+               return
+       }
+
+       yyerror("scale must be 1248: %d", scale)
+}
+
+func cclean() {
+       var g2 Addr2
+
+       g2.from = nullgen
+       g2.to = nullgen
+       outcode(x86.AEND, &g2)
+}
+
+var lastpc *obj.Prog
+
+type Addr2 struct {
+       from obj.Addr
+       to   obj.Addr
+}
+
+func outcode(a int, g2 *Addr2) {
+       var p *obj.Prog
+       var pl *obj.Plist
+
+       if asm.Pass == 1 {
+               goto out
+       }
+
+       p = new(obj.Prog)
+       *p = obj.Prog{}
+       p.Ctxt = asm.Ctxt
+       p.As = int16(a)
+       p.Lineno = stmtline
+       p.From = g2.from
+       p.To = g2.to
+       p.Pc = int64(asm.PC)
+
+       if lastpc == nil {
+               pl = obj.Linknewplist(asm.Ctxt)
+               pl.Firstpc = p
+       } else {
+
+               lastpc.Link = p
+       }
+       lastpc = p
+
+out:
+       if a != x86.AGLOBL && a != x86.ADATA {
+               asm.PC++
+       }
+}
diff --git a/src/cmd/new6a/y.go b/src/cmd/new6a/y.go
new file mode 100644 (file)
index 0000000..16ce70a
--- /dev/null
@@ -0,0 +1,1313 @@
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/x86"
+)
+
+//line a.y:41
+type yySymType struct {
+       yys   int
+       sym   *asm.Sym
+       lval  int64
+       dval  float64
+       sval  string
+       addr  obj.Addr
+       addr2 Addr2
+}
+
+const LTYPE0 = 57346
+const LTYPE1 = 57347
+const LTYPE2 = 57348
+const LTYPE3 = 57349
+const LTYPE4 = 57350
+const LTYPEC = 57351
+const LTYPED = 57352
+const LTYPEN = 57353
+const LTYPER = 57354
+const LTYPET = 57355
+const LTYPEG = 57356
+const LTYPEPC = 57357
+const LTYPES = 57358
+const LTYPEM = 57359
+const LTYPEI = 57360
+const LTYPEXC = 57361
+const LTYPEX = 57362
+const LTYPERT = 57363
+const LTYPEF = 57364
+const LCONST = 57365
+const LFP = 57366
+const LPC = 57367
+const LSB = 57368
+const LBREG = 57369
+const LLREG = 57370
+const LSREG = 57371
+const LFREG = 57372
+const LMREG = 57373
+const LXREG = 57374
+const LFCONST = 57375
+const LSCONST = 57376
+const LSP = 57377
+const LNAME = 57378
+const LLAB = 57379
+const LVAR = 57380
+
+var yyToknames = []string{
+       "'|'",
+       "'^'",
+       "'&'",
+       "'<'",
+       "'>'",
+       "'+'",
+       "'-'",
+       "'*'",
+       "'/'",
+       "'%'",
+       "LTYPE0",
+       "LTYPE1",
+       "LTYPE2",
+       "LTYPE3",
+       "LTYPE4",
+       "LTYPEC",
+       "LTYPED",
+       "LTYPEN",
+       "LTYPER",
+       "LTYPET",
+       "LTYPEG",
+       "LTYPEPC",
+       "LTYPES",
+       "LTYPEM",
+       "LTYPEI",
+       "LTYPEXC",
+       "LTYPEX",
+       "LTYPERT",
+       "LTYPEF",
+       "LCONST",
+       "LFP",
+       "LPC",
+       "LSB",
+       "LBREG",
+       "LLREG",
+       "LSREG",
+       "LFREG",
+       "LMREG",
+       "LXREG",
+       "LFCONST",
+       "LSCONST",
+       "LSP",
+       "LNAME",
+       "LLAB",
+       "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+       -1, 1,
+       1, -1,
+       -2, 2,
+}
+
+const yyNprod = 134
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 565
+
+var yyAct = []int{
+
+       49, 61, 186, 123, 38, 3, 81, 80, 51, 62,
+       47, 188, 269, 268, 267, 71, 70, 118, 86, 48,
+       263, 69, 84, 256, 75, 101, 103, 99, 85, 209,
+       112, 254, 59, 112, 170, 242, 240, 82, 238, 222,
+       220, 211, 55, 54, 210, 64, 171, 111, 241, 235,
+       113, 112, 93, 95, 97, 120, 121, 122, 212, 107,
+       109, 55, 133, 128, 174, 145, 52, 138, 119, 71,
+       115, 129, 208, 232, 112, 136, 139, 169, 55, 54,
+       86, 53, 231, 230, 84, 52, 73, 142, 143, 56,
+       85, 146, 224, 60, 144, 131, 130, 223, 57, 82,
+       53, 154, 52, 153, 37, 132, 152, 66, 56, 151,
+       150, 149, 37, 148, 147, 72, 155, 53, 141, 137,
+       135, 68, 73, 134, 62, 56, 176, 177, 127, 34,
+       114, 32, 31, 112, 120, 28, 229, 29, 71, 30,
+       228, 185, 187, 57, 183, 252, 253, 40, 42, 45,
+       41, 43, 46, 195, 194, 44, 248, 112, 112, 112,
+       112, 112, 166, 168, 112, 112, 112, 247, 182, 167,
+       237, 213, 173, 257, 198, 199, 200, 201, 202, 219,
+       120, 205, 206, 207, 184, 114, 196, 197, 165, 164,
+       163, 161, 162, 156, 157, 158, 159, 160, 184, 264,
+       227, 166, 168, 258, 112, 112, 140, 218, 167, 216,
+       236, 55, 54, 55, 54, 239, 246, 261, 217, 260,
+       35, 233, 234, 226, 255, 243, 214, 244, 181, 33,
+       124, 249, 125, 126, 251, 52, 250, 52, 172, 90,
+       116, 189, 190, 191, 192, 193, 259, 117, 89, 245,
+       53, 7, 53, 125, 126, 73, 262, 73, 56, 62,
+       56, 265, 266, 9, 10, 11, 12, 13, 17, 15,
+       18, 14, 16, 25, 26, 19, 20, 21, 22, 23,
+       24, 27, 55, 54, 83, 156, 157, 158, 159, 160,
+       39, 158, 159, 160, 204, 4, 175, 8, 203, 5,
+       6, 110, 2, 55, 54, 1, 52, 77, 108, 106,
+       40, 42, 45, 41, 43, 46, 105, 104, 44, 87,
+       102, 53, 55, 54, 100, 79, 50, 52, 98, 56,
+       96, 40, 42, 45, 41, 43, 46, 94, 92, 44,
+       57, 88, 53, 55, 54, 83, 52, 50, 78, 62,
+       56, 76, 74, 65, 63, 58, 221, 67, 215, 225,
+       0, 53, 0, 0, 55, 54, 73, 52, 0, 56,
+       0, 40, 42, 45, 41, 43, 46, 0, 0, 44,
+       87, 0, 53, 0, 0, 55, 54, 50, 52, 0,
+       56, 0, 40, 42, 45, 41, 43, 46, 0, 0,
+       44, 57, 0, 53, 0, 0, 0, 91, 50, 52,
+       0, 56, 0, 40, 42, 45, 41, 43, 46, 55,
+       54, 44, 57, 0, 53, 0, 0, 0, 36, 50,
+       0, 0, 56, 0, 0, 0, 55, 54, 0, 0,
+       55, 54, 0, 52, 0, 0, 0, 40, 42, 45,
+       41, 43, 46, 55, 54, 44, 57, 0, 53, 0,
+       52, 0, 0, 50, 52, 0, 56, 0, 40, 42,
+       45, 41, 43, 46, 0, 53, 44, 52, 0, 53,
+       73, 0, 188, 56, 50, 55, 54, 56, 0, 0,
+       72, 0, 53, 0, 55, 179, 0, 73, 55, 54,
+       56, 163, 161, 162, 156, 157, 158, 159, 160, 52,
+       161, 162, 156, 157, 158, 159, 160, 0, 52, 180,
+       0, 0, 52, 0, 53, 0, 0, 0, 178, 73,
+       0, 0, 56, 53, 0, 57, 0, 53, 73, 0,
+       0, 56, 50, 0, 0, 56, 165, 164, 163, 161,
+       162, 156, 157, 158, 159, 160, 164, 163, 161, 162,
+       156, 157, 158, 159, 160,
+}
+var yyPact = []int{
+
+       -1000, -1000, 249, -1000, 86, -1000, 89, 82, 80, 77,
+       376, 294, 294, 410, 69, 97, 489, 273, 355, 294,
+       294, 294, 110, -46, -46, 489, 294, 294, -1000, 33,
+       -1000, -1000, 33, -1000, -1000, -1000, 410, -1000, -1000, -1000,
+       -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17,
+       202, 15, -1000, -1000, 33, 33, 33, 223, -1000, 76,
+       -1000, -1000, 52, -1000, 71, -1000, 68, -1000, 444, -1000,
+       67, 14, 244, 33, -1000, 194, -1000, 66, -1000, 334,
+       -1000, -1000, -1000, 431, -1000, -1000, 12, 223, -1000, -1000,
+       -1000, 410, -1000, 62, -1000, 61, -1000, 59, -1000, 58,
+       -1000, 57, -1000, -1000, -1000, 54, -1000, 51, -1000, 49,
+       249, 542, -1000, 542, -1000, 124, 23, -8, 184, 134,
+       -1000, -1000, -1000, 11, 288, 33, 33, -1000, -1000, -1000,
+       -1000, -1000, 485, 476, 410, 294, -1000, 444, 149, -1000,
+       33, 427, -1000, -1000, -1000, 163, 11, 410, 410, 410,
+       410, 410, 204, 294, 294, -1000, 33, 33, 33, 33,
+       33, 291, 286, 33, 33, 33, 18, -10, -13, 5,
+       33, -1000, -1000, 215, 173, 244, -1000, -1000, -14, 313,
+       -1000, -1000, -1000, -1000, -15, 45, -1000, 40, 190, 91,
+       87, -1000, 31, 30, -1000, 21, -1000, -1000, 280, 280,
+       -1000, -1000, -1000, 33, 33, 503, 495, 551, -4, 33,
+       -1000, -1000, 132, -16, 33, -18, -1000, -1000, -1000, -5,
+       -1000, -19, -1000, -46, -44, -1000, 239, 183, 129, 117,
+       33, 110, -46, 276, 276, 107, -23, 213, -1000, -31,
+       -1000, 137, -1000, -1000, -1000, 170, 236, -1000, -1000, -1000,
+       -1000, -1000, 208, 206, -1000, 33, -1000, -34, -1000, 166,
+       33, 33, -40, -1000, -1000, -41, -42, -1000, -1000, -1000,
+}
+var yyPgo = []int{
+
+       0, 0, 359, 17, 358, 3, 290, 1, 2, 4,
+       8, 6, 93, 32, 7, 10, 19, 229, 357, 220,
+       355, 354, 353, 352, 351, 348, 341, 338, 337, 330,
+       328, 324, 320, 317, 309, 308, 305, 302, 5, 301,
+       300,
+}
+var yyR1 = []int{
+
+       0, 36, 37, 36, 39, 38, 38, 38, 38, 40,
+       40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+       40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+       17, 17, 21, 22, 20, 20, 19, 19, 18, 18,
+       18, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+       28, 28, 29, 29, 29, 30, 31, 32, 32, 33,
+       33, 34, 35, 12, 12, 14, 14, 14, 14, 14,
+       14, 13, 13, 11, 11, 9, 9, 9, 9, 9,
+       9, 9, 8, 7, 7, 7, 7, 7, 7, 7,
+       6, 6, 15, 15, 15, 15, 15, 15, 15, 15,
+       15, 15, 15, 16, 16, 10, 10, 5, 5, 5,
+       4, 4, 4, 1, 1, 1, 1, 1, 1, 2,
+       2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3,
+}
+var yyR2 = []int{
+
+       0, 0, 0, 3, 0, 4, 1, 2, 2, 3,
+       3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       0, 1, 3, 3, 2, 1, 2, 1, 2, 1,
+       3, 5, 3, 5, 2, 1, 1, 1, 3, 5,
+       3, 5, 2, 1, 3, 5, 5, 0, 1, 3,
+       5, 3, 3, 1, 1, 1, 1, 2, 2, 1,
+       1, 1, 1, 4, 2, 1, 1, 1, 1, 1,
+       1, 1, 2, 2, 2, 2, 2, 4, 5, 3,
+       1, 1, 1, 4, 4, 4, 6, 9, 9, 3,
+       3, 5, 8, 1, 6, 5, 7, 0, 2, 2,
+       1, 1, 1, 1, 1, 2, 2, 2, 3, 1,
+       2, 3, 4, 1, 3, 3, 3, 3, 3, 4,
+       4, 3, 3, 3,
+}
+var yyChk = []int{
+
+       -1000, -36, -37, -38, 46, 50, -40, 2, 48, 14,
+       15, 16, 17, 18, 22, 20, 23, 19, 21, 26,
+       27, 28, 29, 30, 31, 24, 25, 32, 49, 51,
+       50, 50, 51, -17, 52, -19, 52, -12, -9, -6,
+       37, 40, 38, 41, 45, 39, 42, -15, -16, -1,
+       53, -10, 33, 48, 10, 9, 56, 46, -20, -13,
+       -12, -7, 55, -21, -13, -22, -12, -18, 52, -11,
+       -7, -1, 46, 53, -23, -10, -24, -6, -25, 52,
+       -14, -11, -16, 11, -9, -15, -1, 46, -26, -17,
+       -19, 52, -27, -13, -28, -13, -29, -13, -30, -9,
+       -31, -7, -32, -7, -33, -6, -34, -13, -35, -13,
+       -39, -3, -1, -3, -12, 53, 38, 45, -3, 53,
+       -1, -1, -1, -5, 7, 9, 10, 52, -1, -10,
+       44, 43, 53, 10, 52, 52, -11, 52, 53, -5,
+       12, 52, -14, -9, -15, 53, -5, 52, 52, 52,
+       52, 52, 52, 52, 52, -38, 9, 10, 11, 12,
+       13, 7, 8, 6, 5, 4, 38, 45, 39, 54,
+       11, 54, 54, 38, 53, 8, -1, -1, 43, 10,
+       43, -12, -13, -11, 35, -1, -8, -1, 55, -12,
+       -12, -12, -12, -12, -7, -1, -13, -13, -3, -3,
+       -3, -3, -3, 7, 8, -3, -3, -3, 54, 11,
+       54, 54, 53, -1, 11, -4, 36, 45, 34, -5,
+       54, 43, 54, 52, 52, -2, 33, 10, 49, 49,
+       52, 52, 52, -3, -3, 53, -1, 38, 54, -1,
+       54, 53, 54, -7, -8, 10, 33, 38, 39, -1,
+       -9, -7, 38, 39, 54, 11, 54, 36, 33, 10,
+       11, 11, -1, 54, 33, -1, -1, 54, 54, 54,
+}
+var yyDef = []int{
+
+       1, -2, 0, 3, 0, 6, 0, 0, 0, 30,
+       0, 0, 0, 0, 0, 0, 0, 0, 30, 0,
+       0, 0, 0, 0, 57, 0, 0, 0, 4, 0,
+       7, 8, 0, 11, 31, 12, 0, 37, 63, 64,
+       75, 76, 77, 78, 79, 80, 81, 90, 91, 92,
+       0, 103, 113, 114, 0, 0, 0, 107, 13, 35,
+       71, 72, 0, 14, 0, 15, 0, 16, 0, 39,
+       0, 0, 107, 0, 17, 0, 18, 0, 19, 0,
+       45, 65, 66, 0, 69, 70, 92, 107, 20, 46,
+       47, 31, 21, 0, 22, 0, 23, 53, 24, 0,
+       25, 0, 26, 58, 27, 0, 28, 0, 29, 0,
+       0, 9, 123, 10, 36, 0, 0, 0, 0, 0,
+       115, 116, 117, 0, 0, 0, 0, 34, 83, 84,
+       85, 86, 0, 0, 0, 0, 38, 0, 0, 74,
+       0, 0, 44, 67, 68, 0, 74, 0, 0, 52,
+       0, 0, 0, 0, 0, 5, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 99,
+       0, 100, 118, 0, 0, 107, 108, 109, 0, 0,
+       89, 32, 33, 40, 0, 0, 42, 0, 0, 48,
+       50, 54, 0, 0, 59, 0, 61, 62, 124, 125,
+       126, 127, 128, 0, 0, 131, 132, 133, 93, 0,
+       94, 95, 0, 0, 0, 0, 110, 111, 112, 0,
+       87, 0, 73, 0, 0, 82, 119, 0, 0, 0,
+       0, 0, 0, 129, 130, 0, 0, 0, 101, 0,
+       105, 0, 88, 41, 43, 0, 120, 49, 51, 55,
+       56, 60, 0, 0, 96, 0, 104, 0, 121, 0,
+       0, 0, 0, 106, 122, 0, 0, 102, 97, 98,
+}
+var yyTok1 = []int{
+
+       1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 55, 13, 6, 3,
+       53, 54, 11, 9, 52, 10, 3, 12, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 49, 50,
+       7, 51, 8, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 4, 3, 56,
+}
+var yyTok2 = []int{
+
+       2, 3, 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,
+}
+var yyTok3 = []int{
+       0,
+}
+
+//line yaccpar:1
+
+/*     parser for yacc output  */
+
+var yyDebug = 0
+
+type yyLexer interface {
+       Lex(lval *yySymType) int
+       Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+       // 4 is TOKSTART above
+       if c >= 4 && c-4 < len(yyToknames) {
+               if yyToknames[c-4] != "" {
+                       return yyToknames[c-4]
+               }
+       }
+       return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+       if s >= 0 && s < len(yyStatenames) {
+               if yyStatenames[s] != "" {
+                       return yyStatenames[s]
+               }
+       }
+       return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+       c := 0
+       char := lex.Lex(lval)
+       if char <= 0 {
+               c = yyTok1[0]
+               goto out
+       }
+       if char < len(yyTok1) {
+               c = yyTok1[char]
+               goto out
+       }
+       if char >= yyPrivate {
+               if char < yyPrivate+len(yyTok2) {
+                       c = yyTok2[char-yyPrivate]
+                       goto out
+               }
+       }
+       for i := 0; i < len(yyTok3); i += 2 {
+               c = yyTok3[i+0]
+               if c == char {
+                       c = yyTok3[i+1]
+                       goto out
+               }
+       }
+
+out:
+       if c == 0 {
+               c = yyTok2[1] /* unknown char */
+       }
+       if yyDebug >= 3 {
+               __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+       }
+       return c
+}
+
+func yyParse(yylex yyLexer) int {
+       var yyn int
+       var yylval yySymType
+       var yyVAL yySymType
+       yyS := make([]yySymType, yyMaxDepth)
+
+       Nerrs := 0   /* number of errors */
+       Errflag := 0 /* error recovery flag */
+       yystate := 0
+       yychar := -1
+       yyp := -1
+       goto yystack
+
+ret0:
+       return 0
+
+ret1:
+       return 1
+
+yystack:
+       /* put a state and value onto the stack */
+       if yyDebug >= 4 {
+               __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+       }
+
+       yyp++
+       if yyp >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyS[yyp] = yyVAL
+       yyS[yyp].yys = yystate
+
+yynewstate:
+       yyn = yyPact[yystate]
+       if yyn <= yyFlag {
+               goto yydefault /* simple state */
+       }
+       if yychar < 0 {
+               yychar = yylex1(yylex, &yylval)
+       }
+       yyn += yychar
+       if yyn < 0 || yyn >= yyLast {
+               goto yydefault
+       }
+       yyn = yyAct[yyn]
+       if yyChk[yyn] == yychar { /* valid shift */
+               yychar = -1
+               yyVAL = yylval
+               yystate = yyn
+               if Errflag > 0 {
+                       Errflag--
+               }
+               goto yystack
+       }
+
+yydefault:
+       /* default state action */
+       yyn = yyDef[yystate]
+       if yyn == -2 {
+               if yychar < 0 {
+                       yychar = yylex1(yylex, &yylval)
+               }
+
+               /* look through exception table */
+               xi := 0
+               for {
+                       if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+                               break
+                       }
+                       xi += 2
+               }
+               for xi += 2; ; xi += 2 {
+                       yyn = yyExca[xi+0]
+                       if yyn < 0 || yyn == yychar {
+                               break
+                       }
+               }
+               yyn = yyExca[xi+1]
+               if yyn < 0 {
+                       goto ret0
+               }
+       }
+       if yyn == 0 {
+               /* error ... attempt to resume parsing */
+               switch Errflag {
+               case 0: /* brand new error */
+                       yylex.Error("syntax error")
+                       Nerrs++
+                       if yyDebug >= 1 {
+                               __yyfmt__.Printf("%s", yyStatname(yystate))
+                               __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+                       }
+                       fallthrough
+
+               case 1, 2: /* incompletely recovered error ... try again */
+                       Errflag = 3
+
+                       /* find a state where "error" is a legal shift action */
+                       for yyp >= 0 {
+                               yyn = yyPact[yyS[yyp].yys] + yyErrCode
+                               if yyn >= 0 && yyn < yyLast {
+                                       yystate = yyAct[yyn] /* simulate a shift of "error" */
+                                       if yyChk[yystate] == yyErrCode {
+                                               goto yystack
+                                       }
+                               }
+
+                               /* the current p has no shift on "error", pop stack */
+                               if yyDebug >= 2 {
+                                       __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+                               }
+                               yyp--
+                       }
+                       /* there is no state on the stack with an error shift ... abort */
+                       goto ret1
+
+               case 3: /* no shift yet; clobber input char */
+                       if yyDebug >= 2 {
+                               __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+                       }
+                       if yychar == yyEofCode {
+                               goto ret1
+                       }
+                       yychar = -1
+                       goto yynewstate /* try again in the same state */
+               }
+       }
+
+       /* reduction by production yyn */
+       if yyDebug >= 2 {
+               __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+       }
+
+       yynt := yyn
+       yypt := yyp
+       _ = yypt // guard against "declared and not used"
+
+       yyp -= yyR2[yyn]
+       // yyp is now the index of $0. Perform the default action. Iff the
+       // reduced production is Îµ, $1 is possibly out of range.
+       if yyp+1 >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyVAL = yyS[yyp+1]
+
+       /* consult goto table to find next state */
+       yyn = yyR1[yyn]
+       yyg := yyPgo[yyn]
+       yyj := yyg + yyS[yyp].yys + 1
+
+       if yyj >= yyLast {
+               yystate = yyAct[yyg]
+       } else {
+               yystate = yyAct[yyj]
+               if yyChk[yystate] != -yyn {
+                       yystate = yyAct[yyg]
+               }
+       }
+       // dummy call; replaced with literal code
+       switch yynt {
+
+       case 2:
+               //line a.y:72
+               {
+                       stmtline = asm.Lineno
+               }
+       case 4:
+               //line a.y:79
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+                               yyerror("redeclaration of %s (%s)", yyS[yypt-1].sym.Labelname, yyS[yypt-1].sym.Name)
+                       }
+                       yyS[yypt-1].sym.Type = LLAB
+                       yyS[yypt-1].sym.Value = int64(asm.PC)
+               }
+       case 9:
+               //line a.y:94
+               {
+                       yyS[yypt-2].sym.Type = LVAR
+                       yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+               }
+       case 10:
+               //line a.y:99
+               {
+                       if yyS[yypt-2].sym.Value != yyS[yypt-0].lval {
+                               yyerror("redeclaration of %s", yyS[yypt-2].sym.Name)
+                       }
+                       yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+               }
+       case 11:
+               //line a.y:105
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 12:
+               //line a.y:106
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 13:
+               //line a.y:107
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 14:
+               //line a.y:108
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 15:
+               //line a.y:109
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 16:
+               //line a.y:110
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 17:
+               //line a.y:111
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 18:
+               //line a.y:112
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 19:
+               //line a.y:113
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 20:
+               //line a.y:114
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 21:
+               //line a.y:115
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 22:
+               //line a.y:116
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 23:
+               //line a.y:117
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 24:
+               //line a.y:118
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 25:
+               //line a.y:119
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 26:
+               //line a.y:120
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 27:
+               //line a.y:121
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 28:
+               //line a.y:122
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 29:
+               //line a.y:123
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 30:
+               //line a.y:126
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = nullgen
+               }
+       case 31:
+               //line a.y:131
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = nullgen
+               }
+       case 32:
+               //line a.y:138
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 33:
+               //line a.y:145
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 34:
+               //line a.y:152
+               {
+                       yyVAL.addr2.from = yyS[yypt-1].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 35:
+               //line a.y:157
+               {
+                       yyVAL.addr2.from = yyS[yypt-0].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 36:
+               //line a.y:164
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 37:
+               //line a.y:169
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 38:
+               //line a.y:176
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 39:
+               //line a.y:181
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 40:
+               //line a.y:186
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 41:
+               //line a.y:193
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 42:
+               //line a.y:201
+               {
+                       asm.Settext(yyS[yypt-2].addr.Sym)
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 43:
+               //line a.y:207
+               {
+                       asm.Settext(yyS[yypt-4].addr.Sym)
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 44:
+               //line a.y:216
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 45:
+               //line a.y:221
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 46:
+               yyVAL.addr2 = yyS[yypt-0].addr2
+       case 47:
+               yyVAL.addr2 = yyS[yypt-0].addr2
+       case 48:
+               //line a.y:232
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 49:
+               //line a.y:237
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       if yyVAL.addr2.from.Index != x86.D_NONE {
+                               yyerror("dp shift with lhs index")
+                       }
+                       yyVAL.addr2.from.Index = uint8(yyS[yypt-0].lval)
+               }
+       case 50:
+               //line a.y:248
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 51:
+               //line a.y:253
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       if yyVAL.addr2.to.Index != x86.D_NONE {
+                               yyerror("dp move with lhs index")
+                       }
+                       yyVAL.addr2.to.Index = uint8(yyS[yypt-0].lval)
+               }
+       case 52:
+               //line a.y:264
+               {
+                       yyVAL.addr2.from = yyS[yypt-1].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 53:
+               //line a.y:269
+               {
+                       yyVAL.addr2.from = yyS[yypt-0].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 54:
+               //line a.y:274
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 55:
+               //line a.y:281
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       yyVAL.addr2.to.Offset = yyS[yypt-0].lval
+               }
+       case 56:
+               //line a.y:289
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+                       if yyS[yypt-4].addr.Type != x86.D_CONST {
+                               yyerror("illegal constant")
+                       }
+                       yyVAL.addr2.to.Offset = yyS[yypt-4].addr.Offset
+               }
+       case 57:
+               //line a.y:299
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = nullgen
+               }
+       case 58:
+               //line a.y:304
+               {
+                       yyVAL.addr2.from = yyS[yypt-0].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 59:
+               //line a.y:311
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 60:
+               //line a.y:316
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 61:
+               //line a.y:324
+               {
+                       if yyS[yypt-2].addr.Type != x86.D_CONST || yyS[yypt-0].addr.Type != x86.D_CONST {
+                               yyerror("arguments to asm.PCDATA must be integer constants")
+                       }
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 62:
+               //line a.y:334
+               {
+                       if yyS[yypt-2].addr.Type != x86.D_CONST {
+                               yyerror("index for FUNCDATA must be integer constant")
+                       }
+                       if yyS[yypt-0].addr.Type != x86.D_EXTERN && yyS[yypt-0].addr.Type != x86.D_STATIC {
+                               yyerror("value for FUNCDATA must be symbol reference")
+                       }
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 63:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 64:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 65:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 66:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 67:
+               //line a.y:353
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 68:
+               //line a.y:357
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 69:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 70:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 71:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 72:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 73:
+               //line a.y:369
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+               }
+       case 74:
+               //line a.y:375
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       yyVAL.addr = nullgen
+                       if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+                               yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyVAL.addr.Type = x86.D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+               }
+       case 75:
+               //line a.y:387
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 76:
+               //line a.y:392
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 77:
+               //line a.y:397
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 78:
+               //line a.y:402
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 79:
+               //line a.y:407
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_SP
+               }
+       case 80:
+               //line a.y:412
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 81:
+               //line a.y:417
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 82:
+               //line a.y:423
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_CONST
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 83:
+               //line a.y:431
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_CONST
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 84:
+               //line a.y:437
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       yyVAL.addr.Index = uint8(yyS[yypt-0].addr.Type)
+                       yyVAL.addr.Type = x86.D_ADDR
+                       /*
+                               if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
+                                       yyerror("constant cannot be automatic: %s",
+                                               $2.sym.Name);
+                       */
+               }
+       case 85:
+               //line a.y:447
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_SCONST
+                       yyVAL.addr.U.Sval = (yyS[yypt-0].sval + "\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
+               }
+       case 86:
+               //line a.y:453
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-0].dval
+               }
+       case 87:
+               //line a.y:459
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-1].dval
+               }
+       case 88:
+               //line a.y:465
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-1].dval
+               }
+       case 89:
+               //line a.y:471
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+               }
+       case 90:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 91:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 92:
+               //line a.y:483
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_INDIR + x86.D_NONE
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 93:
+               //line a.y:489
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 94:
+               //line a.y:495
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_SP)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 95:
+               //line a.y:501
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 96:
+               //line a.y:507
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_NONE)
+                       yyVAL.addr.Offset = yyS[yypt-5].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 97:
+               //line a.y:516
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Offset = yyS[yypt-8].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 98:
+               //line a.y:525
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Offset = yyS[yypt-8].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 99:
+               //line a.y:534
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+               }
+       case 100:
+               //line a.y:539
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_SP)
+               }
+       case 101:
+               //line a.y:544
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_NONE)
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 102:
+               //line a.y:552
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 103:
+               //line a.y:562
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 104:
+               //line a.y:566
+               {
+                       yyVAL.addr = yyS[yypt-5].addr
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 105:
+               //line a.y:575
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 106:
+               //line a.y:582
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = x86.D_STATIC
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 107:
+               //line a.y:590
+               {
+                       yyVAL.lval = 0
+               }
+       case 108:
+               //line a.y:594
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 109:
+               //line a.y:598
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 110:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 111:
+               //line a.y:605
+               {
+                       yyVAL.lval = x86.D_AUTO
+               }
+       case 112:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 113:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 114:
+               //line a.y:613
+               {
+                       yyVAL.lval = yyS[yypt-0].sym.Value
+               }
+       case 115:
+               //line a.y:617
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 116:
+               //line a.y:621
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 117:
+               //line a.y:625
+               {
+                       yyVAL.lval = ^yyS[yypt-0].lval
+               }
+       case 118:
+               //line a.y:629
+               {
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 119:
+               //line a.y:635
+               {
+                       yyVAL.lval = int64(uint64(yyS[yypt-0].lval&0xffffffff) + (obj.ArgsSizeUnknown << 32))
+               }
+       case 120:
+               //line a.y:639
+               {
+                       yyVAL.lval = int64(uint64(-yyS[yypt-0].lval&0xffffffff) + (obj.ArgsSizeUnknown << 32))
+               }
+       case 121:
+               //line a.y:643
+               {
+                       yyVAL.lval = (yyS[yypt-2].lval & 0xffffffff) + ((yyS[yypt-0].lval & 0xffff) << 32)
+               }
+       case 122:
+               //line a.y:647
+               {
+                       yyVAL.lval = (-yyS[yypt-2].lval & 0xffffffff) + ((yyS[yypt-0].lval & 0xffff) << 32)
+               }
+       case 123:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 124:
+               //line a.y:654
+               {
+                       yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+               }
+       case 125:
+               //line a.y:658
+               {
+                       yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+               }
+       case 126:
+               //line a.y:662
+               {
+                       yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+               }
+       case 127:
+               //line a.y:666
+               {
+                       yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+               }
+       case 128:
+               //line a.y:670
+               {
+                       yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+               }
+       case 129:
+               //line a.y:674
+               {
+                       yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+               }
+       case 130:
+               //line a.y:678
+               {
+                       yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+               }
+       case 131:
+               //line a.y:682
+               {
+                       yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+               }
+       case 132:
+               //line a.y:686
+               {
+                       yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+               }
+       case 133:
+               //line a.y:690
+               {
+                       yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+               }
+       }
+       goto yystack /* stack new state and value */
+}
diff --git a/src/cmd/new8a/a.y b/src/cmd/new8a/a.y
new file mode 100644 (file)
index 0000000..878420a
--- /dev/null
@@ -0,0 +1,693 @@
+// Inferno utils/8a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/8a/a.y
+//
+//     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.
+
+%{
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/i386"
+)
+%}
+
+%union {
+       sym *asm.Sym
+       lval int64
+       con2 struct {
+               v1 int32
+               v2 int32
+       }
+       dval float64
+       sval string
+       addr obj.Addr
+       addr2 Addr2
+}
+
+%left  '|'
+%left  '^'
+%left  '&'
+%left  '<' '>'
+%left  '+' '-'
+%left  '*' '/' '%'
+%token <lval>  LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
+%token <lval>  LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
+%token <lval>  LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB
+%token <lval>  LBREG LLREG LSREG LFREG LXREG
+%token <dval>  LFCONST
+%token <sval>  LSCONST LSP
+%token <sym>   LNAME LLAB LVAR
+%type  <lval>  con expr pointer offset
+%type  <con2>  con2
+%type  <addr>  mem imm imm2 reg nam rel rem rim rom omem nmem
+%type  <addr2> nonnon nonrel nonrem rimnon rimrem remrim
+%type  <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12
+%%
+prog:
+|      prog
+       {
+               stmtline = asm.Lineno;
+       }
+       line
+
+line:
+       LNAME ':'
+       {
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
+       }
+       line
+|      ';'
+|      inst ';'
+|      error ';'
+
+inst:
+       LNAME '=' expr
+       {
+               $1.Type = LVAR;
+               $1.Value = $3;
+       }
+|      LVAR '=' expr
+       {
+               if $1.Value != int64($3) {
+                       yyerror("redeclaration of %s", $1.Name);
+               }
+               $1.Value = $3;
+       }
+|      LTYPE0 nonnon   { outcode(int($1), &$2); }
+|      LTYPE1 nonrem   { outcode(int($1), &$2); }
+|      LTYPE2 rimnon   { outcode(int($1), &$2); }
+|      LTYPE3 rimrem   { outcode(int($1), &$2); }
+|      LTYPE4 remrim   { outcode(int($1), &$2); }
+|      LTYPER nonrel   { outcode(int($1), &$2); }
+|      LTYPED spec1    { outcode(int($1), &$2); }
+|      LTYPET spec2    { outcode(int($1), &$2); }
+|      LTYPEC spec3    { outcode(int($1), &$2); }
+|      LTYPEN spec4    { outcode(int($1), &$2); }
+|      LTYPES spec5    { outcode(int($1), &$2); }
+|      LTYPEM spec6    { outcode(int($1), &$2); }
+|      LTYPEI spec7    { outcode(int($1), &$2); }
+|      LTYPEG spec8    { outcode(int($1), &$2); }
+|      LTYPEXC spec9   { outcode(int($1), &$2); }
+|      LTYPEX spec10   { outcode(int($1), &$2); }
+|      LTYPEPC spec11  { outcode(int($1), &$2); }
+|      LTYPEF spec12   { outcode(int($1), &$2); }
+
+nonnon:
+       {
+               $$.from = nullgen;
+               $$.to = nullgen;
+       }
+|      ','
+       {
+               $$.from = nullgen;
+               $$.to = nullgen;
+       }
+
+rimrem:
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+remrim:
+       rem ',' rim
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+rimnon:
+       rim ','
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+
+nonrem:
+       ',' rem
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rem
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+
+nonrel:
+       ',' rel
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rel
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+|      imm ',' rel
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec1: /* DATA */
+       nam '/' con ',' imm
+       {
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec2: /* TEXT */
+       mem ',' imm2
+       {
+               asm.Settext($1.Sym);
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      mem ',' con ',' imm2
+       {
+               asm.Settext($1.Sym);
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec3: /* JMP/CALL */
+       ',' rom
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+       }
+|      rom
+       {
+               $$.from = nullgen;
+               $$.to = $1;
+       }
+|      '*' nam
+       {
+               $$.from = nullgen;
+               $$.to = $2;
+               $$.to.Index = uint8($2.Type)
+               $$.to.Type = D_INDIR+D_ADDR;
+       }
+
+spec4: /* NOP */
+       nonnon
+|      nonrem
+
+spec5: /* SHL/SHR */
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      rim ',' rem ':' LLREG
+       {
+               $$.from = $1;
+               $$.to = $3;
+               if $$.from.Index != D_NONE {
+                       yyerror("dp shift with lhs index");
+               }
+               $$.from.Index = uint8($5);
+       }
+
+spec6: /* MOVW/MOVL */
+       rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      rim ',' rem ':' LSREG
+       {
+               $$.from = $1;
+               $$.to = $3;
+               if $$.to.Index != D_NONE {
+                       yyerror("dp move with lhs index");
+               }
+               $$.to.Index = uint8($5);
+       }
+
+spec7:
+       rim ','
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim
+       {
+               $$.from = $1;
+               $$.to = nullgen;
+       }
+|      rim ',' rem
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec8: /* GLOBL */
+       mem ',' imm
+       {
+               $$.from = $1;
+               $$.to = $3;
+       }
+|      mem ',' con ',' imm
+       {
+               $$.from = $1;
+               $$.from.Scale = int8($3);
+               $$.to = $5;
+       }
+
+spec9: /* CMPPS/CMPPD */
+       reg ',' rem ',' con
+       {
+               $$.from = $1;
+               $$.to = $3;
+               $$.to.Offset = $5;
+       }
+
+spec10:        /* PINSRD */
+       imm ',' rem ',' reg
+       {
+               $$.from = $3;
+               $$.to = $5;
+               if $1.Type != D_CONST {
+                       yyerror("illegal constant")
+               }
+               $$.to.Offset = $1.Offset;
+       }
+
+spec11:        /* PCDATA */
+       rim ',' rim
+       {
+               if $1.Type != D_CONST || $3.Type != D_CONST {
+                       yyerror("arguments to PCDATA must be integer constants");
+               }
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+spec12:        /* FUNCDATA */
+       rim ',' rim
+       {
+               if $1.Type != D_CONST {
+                       yyerror("index for FUNCDATA must be integer constant");
+               }
+               if $3.Type != D_EXTERN && $3.Type != D_STATIC {
+                       yyerror("value for FUNCDATA must be symbol reference");
+               }
+               $$.from = $1;
+               $$.to = $3;
+       }
+
+rem:
+       reg
+|      mem
+
+rom:
+       rel
+|      nmem
+|      '*' reg
+       {
+               $$ = $2;
+       }
+|      '*' omem
+       {
+               $$ = $2;
+       }
+|      reg
+|      omem
+|      imm
+
+rim:
+       rem
+|      imm
+
+rel:
+       con '(' LPC ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
+       }
+|      LNAME offset
+       {
+               $1 = asm.LabelLookup($1);
+               $$ = nullgen;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname);
+               }
+               $$.Type = D_BRANCH;
+               $$.Offset = $1.Value + $2;
+       }
+
+reg:
+       LBREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LFREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LLREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LXREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+|      LSP
+       {
+               $$ = nullgen;
+               $$.Type = D_SP;
+       }
+|      LSREG
+       {
+               $$ = nullgen;
+               $$.Type = int16($1);
+       }
+
+imm:
+       '$' con
+       {
+               $$ = nullgen;
+               $$.Type = D_CONST;
+               $$.Offset = $2;
+       }
+|      '$' nam
+       {
+               $$ = $2;
+               $$.Index = uint8($2.Type);
+               $$.Type = D_ADDR;
+               /*
+               if($2.Type == D_AUTO || $2.Type == D_PARAM)
+                       yyerror("constant cannot be automatic: %s",
+                               $2.Sym.name);
+                */
+       }
+|      '$' LSCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_SCONST;
+               $$.U.Sval = $2
+       }
+|      '$' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = $2;
+       }
+|      '$' '(' LFCONST ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = $3;
+       }
+|      '$' '(' '-' LFCONST ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = -$4;
+       }
+|      '$' '-' LFCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_FCONST;
+               $$.U.Dval = -$3;
+       }
+
+imm2:
+       '$' con2
+       {
+               $$ = nullgen;
+               $$.Type = D_CONST2;
+               $$.Offset = int64($2.v1);
+               $$.Offset2 = int32($2.v2);
+       }
+
+con2:
+       LCONST
+       {
+               $$.v1 = int32($1);
+               $$.v2 = -obj.ArgsSizeUnknown
+       }
+|      '-' LCONST
+       {
+               $$.v1 = int32(-$2);
+               $$.v2 = -obj.ArgsSizeUnknown;
+       }
+|      LCONST '-' LCONST
+       {
+               $$.v1 = int32($1);
+               $$.v2 = int32($3);
+       }
+|      '-' LCONST '-' LCONST
+       {
+               $$.v1 = int32(-$2);
+               $$.v2 = int32($4);
+       }
+
+mem:
+       omem
+|      nmem
+
+omem:
+       con
+       {
+               $$ = nullgen;
+               $$.Type = D_INDIR+D_NONE;
+               $$.Offset = $1;
+       }
+|      con '(' LLREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$3);
+               $$.Offset = $1;
+       }
+|      con '(' LSP ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_INDIR+D_SP;
+               $$.Offset = $1;
+       }
+|      con '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_INDIR+D_NONE;
+               $$.Offset = $1;
+               $$.Index = uint8($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
+       }
+|      con '(' LLREG ')' '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$3);
+               $$.Offset = $1;
+               $$.Index = uint8($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
+       }
+|      con '(' LLREG ')' '(' LSREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$3);
+               $$.Offset = $1;
+               $$.Index = uint8($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
+       }
+|      '(' LLREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$2);
+       }
+|      '(' LSP ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_INDIR+D_SP;
+       }
+|      con '(' LSREG ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$3);
+               $$.Offset = $1;
+       }
+|      '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_INDIR+D_NONE;
+               $$.Index = uint8($2);
+               $$.Scale = int8($4);
+               checkscale($$.Scale);
+       }
+|      '(' LLREG ')' '(' LLREG '*' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16(D_INDIR+$2);
+               $$.Index = uint8($5);
+               $$.Scale = int8($7);
+               checkscale($$.Scale);
+       }
+
+nmem:
+       nam
+       {
+               $$ = $1;
+       }
+|      nam '(' LLREG '*' con ')'
+       {
+               $$ = $1;
+               $$.Index = uint8($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
+       }
+
+nam:
+       LNAME offset '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = int16($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
+       }
+|      LNAME '<' '>' offset '(' LSB ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_STATIC;
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = $4;
+       }
+
+offset:
+       {
+               $$ = 0;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+
+pointer:
+       LSB
+|      LSP
+       {
+               $$ = D_AUTO;
+       }
+|      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 << uint($4);
+       }
+|      expr '>' '>' expr
+       {
+               $$ = $1 >> uint($4);
+       }
+|      expr '&' expr
+       {
+               $$ = $1 & $3;
+       }
+|      expr '^' expr
+       {
+               $$ = $1 ^ $3;
+       }
+|      expr '|' expr
+       {
+               $$ = $1 | $3;
+       }
diff --git a/src/cmd/new8a/lex.go b/src/cmd/new8a/lex.go
new file mode 100644 (file)
index 0000000..cf75953
--- /dev/null
@@ -0,0 +1,771 @@
+// Inferno utils/8a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8a/lex.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.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/i386"
+)
+
+var (
+       yyerror  = asm.Yyerror
+       nullgen  obj.Addr
+       stmtline int32
+)
+
+func main() {
+       cinit()
+
+       asm.LSCONST = LSCONST
+       asm.LCONST = LCONST
+       asm.LFCONST = LFCONST
+       asm.LNAME = LNAME
+       asm.LVAR = LVAR
+       asm.LLAB = LLAB
+
+       asm.Lexinit = lexinit
+       asm.Cclean = cclean
+       asm.Yyparse = yyparse
+
+       asm.Thechar = '8'
+       asm.Thestring = "386"
+       asm.Thelinkarch = &i386.Link386
+
+       asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+       var av asm.Yylval
+       tok := asm.Yylex(&av)
+       v.sym = av.Sym
+       v.lval = av.Lval
+       v.sval = av.Sval
+       v.dval = av.Dval
+       return tok
+}
+
+func (yy) Error(msg string) {
+       asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+       yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+       {"SP", LSP, i386.D_AUTO},
+       {"SB", LSB, i386.D_EXTERN},
+       {"FP", LFP, i386.D_PARAM},
+       {"PC", LPC, i386.D_BRANCH},
+       {"AL", LBREG, i386.D_AL},
+       {"CL", LBREG, i386.D_CL},
+       {"DL", LBREG, i386.D_DL},
+       {"BL", LBREG, i386.D_BL},
+       {"AH", LBREG, i386.D_AH},
+       {"CH", LBREG, i386.D_CH},
+       {"DH", LBREG, i386.D_DH},
+       {"BH", LBREG, i386.D_BH},
+       {"AX", LLREG, i386.D_AX},
+       {"CX", LLREG, i386.D_CX},
+       {"DX", LLREG, i386.D_DX},
+       {"BX", LLREG, i386.D_BX},
+       /*      "SP",           LLREG,  D_SP,   */
+       {"BP", LLREG, i386.D_BP},
+       {"SI", LLREG, i386.D_SI},
+       {"DI", LLREG, i386.D_DI},
+       {"F0", LFREG, i386.D_F0 + 0},
+       {"F1", LFREG, i386.D_F0 + 1},
+       {"F2", LFREG, i386.D_F0 + 2},
+       {"F3", LFREG, i386.D_F0 + 3},
+       {"F4", LFREG, i386.D_F0 + 4},
+       {"F5", LFREG, i386.D_F0 + 5},
+       {"F6", LFREG, i386.D_F0 + 6},
+       {"F7", LFREG, i386.D_F0 + 7},
+       {"X0", LXREG, i386.D_X0 + 0},
+       {"X1", LXREG, i386.D_X0 + 1},
+       {"X2", LXREG, i386.D_X0 + 2},
+       {"X3", LXREG, i386.D_X0 + 3},
+       {"X4", LXREG, i386.D_X0 + 4},
+       {"X5", LXREG, i386.D_X0 + 5},
+       {"X6", LXREG, i386.D_X0 + 6},
+       {"X7", LXREG, i386.D_X0 + 7},
+       {"CS", LSREG, i386.D_CS},
+       {"SS", LSREG, i386.D_SS},
+       {"DS", LSREG, i386.D_DS},
+       {"ES", LSREG, i386.D_ES},
+       {"FS", LSREG, i386.D_FS},
+       {"GS", LSREG, i386.D_GS},
+       {"TLS", LSREG, i386.D_TLS},
+       {"GDTR", LBREG, i386.D_GDTR},
+       {"IDTR", LBREG, i386.D_IDTR},
+       {"LDTR", LBREG, i386.D_LDTR},
+       {"MSW", LBREG, i386.D_MSW},
+       {"TASK", LBREG, i386.D_TASK},
+       {"CR0", LBREG, i386.D_CR + 0},
+       {"CR1", LBREG, i386.D_CR + 1},
+       {"CR2", LBREG, i386.D_CR + 2},
+       {"CR3", LBREG, i386.D_CR + 3},
+       {"CR4", LBREG, i386.D_CR + 4},
+       {"CR5", LBREG, i386.D_CR + 5},
+       {"CR6", LBREG, i386.D_CR + 6},
+       {"CR7", LBREG, i386.D_CR + 7},
+       {"DR0", LBREG, i386.D_DR + 0},
+       {"DR1", LBREG, i386.D_DR + 1},
+       {"DR2", LBREG, i386.D_DR + 2},
+       {"DR3", LBREG, i386.D_DR + 3},
+       {"DR4", LBREG, i386.D_DR + 4},
+       {"DR5", LBREG, i386.D_DR + 5},
+       {"DR6", LBREG, i386.D_DR + 6},
+       {"DR7", LBREG, i386.D_DR + 7},
+       {"TR0", LBREG, i386.D_TR + 0},
+       {"TR1", LBREG, i386.D_TR + 1},
+       {"TR2", LBREG, i386.D_TR + 2},
+       {"TR3", LBREG, i386.D_TR + 3},
+       {"TR4", LBREG, i386.D_TR + 4},
+       {"TR5", LBREG, i386.D_TR + 5},
+       {"TR6", LBREG, i386.D_TR + 6},
+       {"TR7", LBREG, i386.D_TR + 7},
+       {"AAA", LTYPE0, i386.AAAA},
+       {"AAD", LTYPE0, i386.AAAD},
+       {"AAM", LTYPE0, i386.AAAM},
+       {"AAS", LTYPE0, i386.AAAS},
+       {"ADCB", LTYPE3, i386.AADCB},
+       {"ADCL", LTYPE3, i386.AADCL},
+       {"ADCW", LTYPE3, i386.AADCW},
+       {"ADDB", LTYPE3, i386.AADDB},
+       {"ADDL", LTYPE3, i386.AADDL},
+       {"ADDW", LTYPE3, i386.AADDW},
+       {"ADJSP", LTYPE2, i386.AADJSP},
+       {"ANDB", LTYPE3, i386.AANDB},
+       {"ANDL", LTYPE3, i386.AANDL},
+       {"ANDW", LTYPE3, i386.AANDW},
+       {"ARPL", LTYPE3, i386.AARPL},
+       {"BOUNDL", LTYPE3, i386.ABOUNDL},
+       {"BOUNDW", LTYPE3, i386.ABOUNDW},
+       {"BSFL", LTYPE3, i386.ABSFL},
+       {"BSFW", LTYPE3, i386.ABSFW},
+       {"BSRL", LTYPE3, i386.ABSRL},
+       {"BSRW", LTYPE3, i386.ABSRW},
+       {"BSWAPL", LTYPE1, i386.ABSWAPL},
+       {"BTCL", LTYPE3, i386.ABTCL},
+       {"BTCW", LTYPE3, i386.ABTCW},
+       {"BTL", LTYPE3, i386.ABTL},
+       {"BTRL", LTYPE3, i386.ABTRL},
+       {"BTRW", LTYPE3, i386.ABTRW},
+       {"BTSL", LTYPE3, i386.ABTSL},
+       {"BTSW", LTYPE3, i386.ABTSW},
+       {"BTW", LTYPE3, i386.ABTW},
+       {"BYTE", LTYPE2, i386.ABYTE},
+       {"CALL", LTYPEC, i386.ACALL},
+       {"CLC", LTYPE0, i386.ACLC},
+       {"CLD", LTYPE0, i386.ACLD},
+       {"CLI", LTYPE0, i386.ACLI},
+       {"CLTS", LTYPE0, i386.ACLTS},
+       {"CMC", LTYPE0, i386.ACMC},
+       {"CMPB", LTYPE4, i386.ACMPB},
+       {"CMPL", LTYPE4, i386.ACMPL},
+       {"CMPW", LTYPE4, i386.ACMPW},
+       {"CMPSB", LTYPE0, i386.ACMPSB},
+       {"CMPSL", LTYPE0, i386.ACMPSL},
+       {"CMPSW", LTYPE0, i386.ACMPSW},
+       {"CMPXCHG8B", LTYPE1, i386.ACMPXCHG8B},
+       {"CMPXCHGB", LTYPE3, i386.ACMPXCHGB},
+       {"CMPXCHGL", LTYPE3, i386.ACMPXCHGL},
+       {"CMPXCHGW", LTYPE3, i386.ACMPXCHGW},
+       {"CPUID", LTYPE0, i386.ACPUID},
+       {"DAA", LTYPE0, i386.ADAA},
+       {"DAS", LTYPE0, i386.ADAS},
+       {"DATA", LTYPED, i386.ADATA},
+       {"DECB", LTYPE1, i386.ADECB},
+       {"DECL", LTYPE1, i386.ADECL},
+       {"DECW", LTYPE1, i386.ADECW},
+       {"DIVB", LTYPE2, i386.ADIVB},
+       {"DIVL", LTYPE2, i386.ADIVL},
+       {"DIVW", LTYPE2, i386.ADIVW},
+       {"END", LTYPE0, i386.AEND},
+       {"ENTER", LTYPE2, i386.AENTER},
+       {"GLOBL", LTYPEG, i386.AGLOBL},
+       {"HLT", LTYPE0, i386.AHLT},
+       {"IDIVB", LTYPE2, i386.AIDIVB},
+       {"IDIVL", LTYPE2, i386.AIDIVL},
+       {"IDIVW", LTYPE2, i386.AIDIVW},
+       {"IMULB", LTYPE2, i386.AIMULB},
+       {"IMULL", LTYPEI, i386.AIMULL},
+       {"IMULW", LTYPEI, i386.AIMULW},
+       {"INB", LTYPE0, i386.AINB},
+       {"INL", LTYPE0, i386.AINL},
+       {"INW", LTYPE0, i386.AINW},
+       {"INCB", LTYPE1, i386.AINCB},
+       {"INCL", LTYPE1, i386.AINCL},
+       {"INCW", LTYPE1, i386.AINCW},
+       {"INSB", LTYPE0, i386.AINSB},
+       {"INSL", LTYPE0, i386.AINSL},
+       {"INSW", LTYPE0, i386.AINSW},
+       {"INT", LTYPE2, i386.AINT},
+       {"INTO", LTYPE0, i386.AINTO},
+       {"IRETL", LTYPE0, i386.AIRETL},
+       {"IRETW", LTYPE0, i386.AIRETW},
+       {"JOS", LTYPER, i386.AJOS},  /* overflow set (OF = 1) */
+       {"JO", LTYPER, i386.AJOS},   /* alternate */
+       {"JOC", LTYPER, i386.AJOC},  /* overflow clear (OF = 0) */
+       {"JNO", LTYPER, i386.AJOC},  /* alternate */
+       {"JCS", LTYPER, i386.AJCS},  /* carry set (CF = 1) */
+       {"JB", LTYPER, i386.AJCS},   /* alternate */
+       {"JC", LTYPER, i386.AJCS},   /* alternate */
+       {"JNAE", LTYPER, i386.AJCS}, /* alternate */
+       {"JLO", LTYPER, i386.AJCS},  /* alternate */
+       {"JCC", LTYPER, i386.AJCC},  /* carry clear (CF = 0) */
+       {"JAE", LTYPER, i386.AJCC},  /* alternate */
+       {"JNB", LTYPER, i386.AJCC},  /* alternate */
+       {"JNC", LTYPER, i386.AJCC},  /* alternate */
+       {"JHS", LTYPER, i386.AJCC},  /* alternate */
+       {"JEQ", LTYPER, i386.AJEQ},  /* equal (ZF = 1) */
+       {"JE", LTYPER, i386.AJEQ},   /* alternate */
+       {"JZ", LTYPER, i386.AJEQ},   /* alternate */
+       {"JNE", LTYPER, i386.AJNE},  /* not equal (ZF = 0) */
+       {"JNZ", LTYPER, i386.AJNE},  /* alternate */
+       {"JLS", LTYPER, i386.AJLS},  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
+       {"JBE", LTYPER, i386.AJLS},  /* alternate */
+       {"JNA", LTYPER, i386.AJLS},  /* alternate */
+       {"JHI", LTYPER, i386.AJHI},  /* higher (unsigned) (CF = 0 && ZF = 0) */
+       {"JA", LTYPER, i386.AJHI},   /* alternate */
+       {"JNBE", LTYPER, i386.AJHI}, /* alternate */
+       {"JMI", LTYPER, i386.AJMI},  /* negative (minus) (SF = 1) */
+       {"JS", LTYPER, i386.AJMI},   /* alternate */
+       {"JPL", LTYPER, i386.AJPL},  /* non-negative (plus) (SF = 0) */
+       {"JNS", LTYPER, i386.AJPL},  /* alternate */
+       {"JPS", LTYPER, i386.AJPS},  /* parity set (PF = 1) */
+       {"JP", LTYPER, i386.AJPS},   /* alternate */
+       {"JPE", LTYPER, i386.AJPS},  /* alternate */
+       {"JPC", LTYPER, i386.AJPC},  /* parity clear (PF = 0) */
+       {"JNP", LTYPER, i386.AJPC},  /* alternate */
+       {"JPO", LTYPER, i386.AJPC},  /* alternate */
+       {"JLT", LTYPER, i386.AJLT},  /* less than (signed) (SF != OF) */
+       {"JL", LTYPER, i386.AJLT},   /* alternate */
+       {"JNGE", LTYPER, i386.AJLT}, /* alternate */
+       {"JGE", LTYPER, i386.AJGE},  /* greater than or equal (signed) (SF = OF) */
+       {"JNL", LTYPER, i386.AJGE},  /* alternate */
+       {"JLE", LTYPER, i386.AJLE},  /* less than or equal (signed) (ZF = 1 || SF != OF) */
+       {"JNG", LTYPER, i386.AJLE},  /* alternate */
+       {"JGT", LTYPER, i386.AJGT},  /* greater than (signed) (ZF = 0 && SF = OF) */
+       {"JG", LTYPER, i386.AJGT},   /* alternate */
+       {"JNLE", LTYPER, i386.AJGT}, /* alternate */
+       {"JCXZL", LTYPER, i386.AJCXZL},
+       {"JCXZW", LTYPER, i386.AJCXZW},
+       {"JMP", LTYPEC, i386.AJMP},
+       {"LAHF", LTYPE0, i386.ALAHF},
+       {"LARL", LTYPE3, i386.ALARL},
+       {"LARW", LTYPE3, i386.ALARW},
+       {"LEAL", LTYPE3, i386.ALEAL},
+       {"LEAW", LTYPE3, i386.ALEAW},
+       {"LEAVEL", LTYPE0, i386.ALEAVEL},
+       {"LEAVEW", LTYPE0, i386.ALEAVEW},
+       {"LOCK", LTYPE0, i386.ALOCK},
+       {"LODSB", LTYPE0, i386.ALODSB},
+       {"LODSL", LTYPE0, i386.ALODSL},
+       {"LODSW", LTYPE0, i386.ALODSW},
+       {"LONG", LTYPE2, i386.ALONG},
+       {"LOOP", LTYPER, i386.ALOOP},
+       {"LOOPEQ", LTYPER, i386.ALOOPEQ},
+       {"LOOPNE", LTYPER, i386.ALOOPNE},
+       {"LSLL", LTYPE3, i386.ALSLL},
+       {"LSLW", LTYPE3, i386.ALSLW},
+       {"MOVB", LTYPE3, i386.AMOVB},
+       {"MOVL", LTYPEM, i386.AMOVL},
+       {"MOVW", LTYPEM, i386.AMOVW},
+       {"MOVQ", LTYPEM, i386.AMOVQ},
+       {"MOVBLSX", LTYPE3, i386.AMOVBLSX},
+       {"MOVBLZX", LTYPE3, i386.AMOVBLZX},
+       {"MOVBWSX", LTYPE3, i386.AMOVBWSX},
+       {"MOVBWZX", LTYPE3, i386.AMOVBWZX},
+       {"MOVWLSX", LTYPE3, i386.AMOVWLSX},
+       {"MOVWLZX", LTYPE3, i386.AMOVWLZX},
+       {"MOVSB", LTYPE0, i386.AMOVSB},
+       {"MOVSL", LTYPE0, i386.AMOVSL},
+       {"MOVSW", LTYPE0, i386.AMOVSW},
+       {"MULB", LTYPE2, i386.AMULB},
+       {"MULL", LTYPE2, i386.AMULL},
+       {"MULW", LTYPE2, i386.AMULW},
+       {"NEGB", LTYPE1, i386.ANEGB},
+       {"NEGL", LTYPE1, i386.ANEGL},
+       {"NEGW", LTYPE1, i386.ANEGW},
+       {"NOP", LTYPEN, i386.ANOP},
+       {"NOTB", LTYPE1, i386.ANOTB},
+       {"NOTL", LTYPE1, i386.ANOTL},
+       {"NOTW", LTYPE1, i386.ANOTW},
+       {"ORB", LTYPE3, i386.AORB},
+       {"ORL", LTYPE3, i386.AORL},
+       {"ORW", LTYPE3, i386.AORW},
+       {"OUTB", LTYPE0, i386.AOUTB},
+       {"OUTL", LTYPE0, i386.AOUTL},
+       {"OUTW", LTYPE0, i386.AOUTW},
+       {"OUTSB", LTYPE0, i386.AOUTSB},
+       {"OUTSL", LTYPE0, i386.AOUTSL},
+       {"OUTSW", LTYPE0, i386.AOUTSW},
+       {"PAUSE", LTYPEN, i386.APAUSE},
+       {"PINSRD", LTYPEX, i386.APINSRD},
+       {"POPAL", LTYPE0, i386.APOPAL},
+       {"POPAW", LTYPE0, i386.APOPAW},
+       {"POPFL", LTYPE0, i386.APOPFL},
+       {"POPFW", LTYPE0, i386.APOPFW},
+       {"POPL", LTYPE1, i386.APOPL},
+       {"POPW", LTYPE1, i386.APOPW},
+       {"PUSHAL", LTYPE0, i386.APUSHAL},
+       {"PUSHAW", LTYPE0, i386.APUSHAW},
+       {"PUSHFL", LTYPE0, i386.APUSHFL},
+       {"PUSHFW", LTYPE0, i386.APUSHFW},
+       {"PUSHL", LTYPE2, i386.APUSHL},
+       {"PUSHW", LTYPE2, i386.APUSHW},
+       {"RCLB", LTYPE3, i386.ARCLB},
+       {"RCLL", LTYPE3, i386.ARCLL},
+       {"RCLW", LTYPE3, i386.ARCLW},
+       {"RCRB", LTYPE3, i386.ARCRB},
+       {"RCRL", LTYPE3, i386.ARCRL},
+       {"RCRW", LTYPE3, i386.ARCRW},
+       {"RDTSC", LTYPE0, i386.ARDTSC},
+       {"REP", LTYPE0, i386.AREP},
+       {"REPN", LTYPE0, i386.AREPN},
+       {"RET", LTYPE0, i386.ARET},
+       {"ROLB", LTYPE3, i386.AROLB},
+       {"ROLL", LTYPE3, i386.AROLL},
+       {"ROLW", LTYPE3, i386.AROLW},
+       {"RORB", LTYPE3, i386.ARORB},
+       {"RORL", LTYPE3, i386.ARORL},
+       {"RORW", LTYPE3, i386.ARORW},
+       {"SAHF", LTYPE0, i386.ASAHF},
+       {"SALB", LTYPE3, i386.ASALB},
+       {"SALL", LTYPE3, i386.ASALL},
+       {"SALW", LTYPE3, i386.ASALW},
+       {"SARB", LTYPE3, i386.ASARB},
+       {"SARL", LTYPE3, i386.ASARL},
+       {"SARW", LTYPE3, i386.ASARW},
+       {"SBBB", LTYPE3, i386.ASBBB},
+       {"SBBL", LTYPE3, i386.ASBBL},
+       {"SBBW", LTYPE3, i386.ASBBW},
+       {"SCASB", LTYPE0, i386.ASCASB},
+       {"SCASL", LTYPE0, i386.ASCASL},
+       {"SCASW", LTYPE0, i386.ASCASW},
+       {"SETCC", LTYPE1, i386.ASETCC}, /* see JCC etc above for condition codes */
+       {"SETCS", LTYPE1, i386.ASETCS},
+       {"SETEQ", LTYPE1, i386.ASETEQ},
+       {"SETGE", LTYPE1, i386.ASETGE},
+       {"SETGT", LTYPE1, i386.ASETGT},
+       {"SETHI", LTYPE1, i386.ASETHI},
+       {"SETLE", LTYPE1, i386.ASETLE},
+       {"SETLS", LTYPE1, i386.ASETLS},
+       {"SETLT", LTYPE1, i386.ASETLT},
+       {"SETMI", LTYPE1, i386.ASETMI},
+       {"SETNE", LTYPE1, i386.ASETNE},
+       {"SETOC", LTYPE1, i386.ASETOC},
+       {"SETOS", LTYPE1, i386.ASETOS},
+       {"SETPC", LTYPE1, i386.ASETPC},
+       {"SETPL", LTYPE1, i386.ASETPL},
+       {"SETPS", LTYPE1, i386.ASETPS},
+       {"CDQ", LTYPE0, i386.ACDQ},
+       {"CWD", LTYPE0, i386.ACWD},
+       {"SHLB", LTYPE3, i386.ASHLB},
+       {"SHLL", LTYPES, i386.ASHLL},
+       {"SHLW", LTYPES, i386.ASHLW},
+       {"SHRB", LTYPE3, i386.ASHRB},
+       {"SHRL", LTYPES, i386.ASHRL},
+       {"SHRW", LTYPES, i386.ASHRW},
+       {"STC", LTYPE0, i386.ASTC},
+       {"STD", LTYPE0, i386.ASTD},
+       {"STI", LTYPE0, i386.ASTI},
+       {"STOSB", LTYPE0, i386.ASTOSB},
+       {"STOSL", LTYPE0, i386.ASTOSL},
+       {"STOSW", LTYPE0, i386.ASTOSW},
+       {"SUBB", LTYPE3, i386.ASUBB},
+       {"SUBL", LTYPE3, i386.ASUBL},
+       {"SUBW", LTYPE3, i386.ASUBW},
+       {"SYSCALL", LTYPE0, i386.ASYSCALL},
+       {"TESTB", LTYPE3, i386.ATESTB},
+       {"TESTL", LTYPE3, i386.ATESTL},
+       {"TESTW", LTYPE3, i386.ATESTW},
+       {"TEXT", LTYPET, i386.ATEXT},
+       {"VERR", LTYPE2, i386.AVERR},
+       {"VERW", LTYPE2, i386.AVERW},
+       {"WAIT", LTYPE0, i386.AWAIT},
+       {"WORD", LTYPE2, i386.AWORD},
+       {"XADDB", LTYPE3, i386.AXADDB},
+       {"XADDL", LTYPE3, i386.AXADDL},
+       {"XADDW", LTYPE3, i386.AXADDW},
+       {"XCHGB", LTYPE3, i386.AXCHGB},
+       {"XCHGL", LTYPE3, i386.AXCHGL},
+       {"XCHGW", LTYPE3, i386.AXCHGW},
+       {"XLAT", LTYPE2, i386.AXLAT},
+       {"XORB", LTYPE3, i386.AXORB},
+       {"XORL", LTYPE3, i386.AXORL},
+       {"XORW", LTYPE3, i386.AXORW},
+       {"CMOVLCC", LTYPE3, i386.ACMOVLCC},
+       {"CMOVLCS", LTYPE3, i386.ACMOVLCS},
+       {"CMOVLEQ", LTYPE3, i386.ACMOVLEQ},
+       {"CMOVLGE", LTYPE3, i386.ACMOVLGE},
+       {"CMOVLGT", LTYPE3, i386.ACMOVLGT},
+       {"CMOVLHI", LTYPE3, i386.ACMOVLHI},
+       {"CMOVLLE", LTYPE3, i386.ACMOVLLE},
+       {"CMOVLLS", LTYPE3, i386.ACMOVLLS},
+       {"CMOVLLT", LTYPE3, i386.ACMOVLLT},
+       {"CMOVLMI", LTYPE3, i386.ACMOVLMI},
+       {"CMOVLNE", LTYPE3, i386.ACMOVLNE},
+       {"CMOVLOC", LTYPE3, i386.ACMOVLOC},
+       {"CMOVLOS", LTYPE3, i386.ACMOVLOS},
+       {"CMOVLPC", LTYPE3, i386.ACMOVLPC},
+       {"CMOVLPL", LTYPE3, i386.ACMOVLPL},
+       {"CMOVLPS", LTYPE3, i386.ACMOVLPS},
+       {"CMOVWCC", LTYPE3, i386.ACMOVWCC},
+       {"CMOVWCS", LTYPE3, i386.ACMOVWCS},
+       {"CMOVWEQ", LTYPE3, i386.ACMOVWEQ},
+       {"CMOVWGE", LTYPE3, i386.ACMOVWGE},
+       {"CMOVWGT", LTYPE3, i386.ACMOVWGT},
+       {"CMOVWHI", LTYPE3, i386.ACMOVWHI},
+       {"CMOVWLE", LTYPE3, i386.ACMOVWLE},
+       {"CMOVWLS", LTYPE3, i386.ACMOVWLS},
+       {"CMOVWLT", LTYPE3, i386.ACMOVWLT},
+       {"CMOVWMI", LTYPE3, i386.ACMOVWMI},
+       {"CMOVWNE", LTYPE3, i386.ACMOVWNE},
+       {"CMOVWOC", LTYPE3, i386.ACMOVWOC},
+       {"CMOVWOS", LTYPE3, i386.ACMOVWOS},
+       {"CMOVWPC", LTYPE3, i386.ACMOVWPC},
+       {"CMOVWPL", LTYPE3, i386.ACMOVWPL},
+       {"CMOVWPS", LTYPE3, i386.ACMOVWPS},
+       {"FMOVB", LTYPE3, i386.AFMOVB},
+       {"FMOVBP", LTYPE3, i386.AFMOVBP},
+       {"FMOVD", LTYPE3, i386.AFMOVD},
+       {"FMOVDP", LTYPE3, i386.AFMOVDP},
+       {"FMOVF", LTYPE3, i386.AFMOVF},
+       {"FMOVFP", LTYPE3, i386.AFMOVFP},
+       {"FMOVL", LTYPE3, i386.AFMOVL},
+       {"FMOVLP", LTYPE3, i386.AFMOVLP},
+       {"FMOVV", LTYPE3, i386.AFMOVV},
+       {"FMOVVP", LTYPE3, i386.AFMOVVP},
+       {"FMOVW", LTYPE3, i386.AFMOVW},
+       {"FMOVWP", LTYPE3, i386.AFMOVWP},
+       {"FMOVX", LTYPE3, i386.AFMOVX},
+       {"FMOVXP", LTYPE3, i386.AFMOVXP},
+       {"FCMOVCC", LTYPE3, i386.AFCMOVCC},
+       {"FCMOVCS", LTYPE3, i386.AFCMOVCS},
+       {"FCMOVEQ", LTYPE3, i386.AFCMOVEQ},
+       {"FCMOVHI", LTYPE3, i386.AFCMOVHI},
+       {"FCMOVLS", LTYPE3, i386.AFCMOVLS},
+       {"FCMOVNE", LTYPE3, i386.AFCMOVNE},
+       {"FCMOVNU", LTYPE3, i386.AFCMOVNU},
+       {"FCMOVUN", LTYPE3, i386.AFCMOVUN},
+       {"FCOMB", LTYPE3, i386.AFCOMB},
+       {"FCOMBP", LTYPE3, i386.AFCOMBP},
+       {"FCOMD", LTYPE3, i386.AFCOMD},
+       {"FCOMDP", LTYPE3, i386.AFCOMDP},
+       {"FCOMDPP", LTYPE3, i386.AFCOMDPP},
+       {"FCOMF", LTYPE3, i386.AFCOMF},
+       {"FCOMFP", LTYPE3, i386.AFCOMFP},
+       {"FCOMI", LTYPE3, i386.AFCOMI},
+       {"FCOMIP", LTYPE3, i386.AFCOMIP},
+       {"FCOML", LTYPE3, i386.AFCOML},
+       {"FCOMLP", LTYPE3, i386.AFCOMLP},
+       {"FCOMW", LTYPE3, i386.AFCOMW},
+       {"FCOMWP", LTYPE3, i386.AFCOMWP},
+       {"FUCOM", LTYPE3, i386.AFUCOM},
+       {"FUCOMI", LTYPE3, i386.AFUCOMI},
+       {"FUCOMIP", LTYPE3, i386.AFUCOMIP},
+       {"FUCOMP", LTYPE3, i386.AFUCOMP},
+       {"FUCOMPP", LTYPE3, i386.AFUCOMPP},
+       {"FADDW", LTYPE3, i386.AFADDW},
+       {"FADDL", LTYPE3, i386.AFADDL},
+       {"FADDF", LTYPE3, i386.AFADDF},
+       {"FADDD", LTYPE3, i386.AFADDD},
+       {"FADDDP", LTYPE3, i386.AFADDDP},
+       {"FSUBDP", LTYPE3, i386.AFSUBDP},
+       {"FSUBW", LTYPE3, i386.AFSUBW},
+       {"FSUBL", LTYPE3, i386.AFSUBL},
+       {"FSUBF", LTYPE3, i386.AFSUBF},
+       {"FSUBD", LTYPE3, i386.AFSUBD},
+       {"FSUBRDP", LTYPE3, i386.AFSUBRDP},
+       {"FSUBRW", LTYPE3, i386.AFSUBRW},
+       {"FSUBRL", LTYPE3, i386.AFSUBRL},
+       {"FSUBRF", LTYPE3, i386.AFSUBRF},
+       {"FSUBRD", LTYPE3, i386.AFSUBRD},
+       {"FMULDP", LTYPE3, i386.AFMULDP},
+       {"FMULW", LTYPE3, i386.AFMULW},
+       {"FMULL", LTYPE3, i386.AFMULL},
+       {"FMULF", LTYPE3, i386.AFMULF},
+       {"FMULD", LTYPE3, i386.AFMULD},
+       {"FDIVDP", LTYPE3, i386.AFDIVDP},
+       {"FDIVW", LTYPE3, i386.AFDIVW},
+       {"FDIVL", LTYPE3, i386.AFDIVL},
+       {"FDIVF", LTYPE3, i386.AFDIVF},
+       {"FDIVD", LTYPE3, i386.AFDIVD},
+       {"FDIVRDP", LTYPE3, i386.AFDIVRDP},
+       {"FDIVRW", LTYPE3, i386.AFDIVRW},
+       {"FDIVRL", LTYPE3, i386.AFDIVRL},
+       {"FDIVRF", LTYPE3, i386.AFDIVRF},
+       {"FDIVRD", LTYPE3, i386.AFDIVRD},
+       {"FXCHD", LTYPE3, i386.AFXCHD},
+       {"FFREE", LTYPE1, i386.AFFREE},
+       {"FLDCW", LTYPE2, i386.AFLDCW},
+       {"FLDENV", LTYPE1, i386.AFLDENV},
+       {"FRSTOR", LTYPE2, i386.AFRSTOR},
+       {"FSAVE", LTYPE1, i386.AFSAVE},
+       {"FSTCW", LTYPE1, i386.AFSTCW},
+       {"FSTENV", LTYPE1, i386.AFSTENV},
+       {"FSTSW", LTYPE1, i386.AFSTSW},
+       {"F2XM1", LTYPE0, i386.AF2XM1},
+       {"FABS", LTYPE0, i386.AFABS},
+       {"FCHS", LTYPE0, i386.AFCHS},
+       {"FCLEX", LTYPE0, i386.AFCLEX},
+       {"FCOS", LTYPE0, i386.AFCOS},
+       {"FDECSTP", LTYPE0, i386.AFDECSTP},
+       {"FINCSTP", LTYPE0, i386.AFINCSTP},
+       {"FINIT", LTYPE0, i386.AFINIT},
+       {"FLD1", LTYPE0, i386.AFLD1},
+       {"FLDL2E", LTYPE0, i386.AFLDL2E},
+       {"FLDL2T", LTYPE0, i386.AFLDL2T},
+       {"FLDLG2", LTYPE0, i386.AFLDLG2},
+       {"FLDLN2", LTYPE0, i386.AFLDLN2},
+       {"FLDPI", LTYPE0, i386.AFLDPI},
+       {"FLDZ", LTYPE0, i386.AFLDZ},
+       {"FNOP", LTYPE0, i386.AFNOP},
+       {"FPATAN", LTYPE0, i386.AFPATAN},
+       {"FPREM", LTYPE0, i386.AFPREM},
+       {"FPREM1", LTYPE0, i386.AFPREM1},
+       {"FPTAN", LTYPE0, i386.AFPTAN},
+       {"FRNDINT", LTYPE0, i386.AFRNDINT},
+       {"FSCALE", LTYPE0, i386.AFSCALE},
+       {"FSIN", LTYPE0, i386.AFSIN},
+       {"FSINCOS", LTYPE0, i386.AFSINCOS},
+       {"FSQRT", LTYPE0, i386.AFSQRT},
+       {"FTST", LTYPE0, i386.AFTST},
+       {"FXAM", LTYPE0, i386.AFXAM},
+       {"FXTRACT", LTYPE0, i386.AFXTRACT},
+       {"FYL2X", LTYPE0, i386.AFYL2X},
+       {"FYL2XP1", LTYPE0, i386.AFYL2XP1},
+       {"LFENCE", LTYPE0, i386.ALFENCE},
+       {"MFENCE", LTYPE0, i386.AMFENCE},
+       {"SFENCE", LTYPE0, i386.ASFENCE},
+       {"EMMS", LTYPE0, i386.AEMMS},
+       {"PREFETCHT0", LTYPE2, i386.APREFETCHT0},
+       {"PREFETCHT1", LTYPE2, i386.APREFETCHT1},
+       {"PREFETCHT2", LTYPE2, i386.APREFETCHT2},
+       {"PREFETCHNTA", LTYPE2, i386.APREFETCHNTA},
+       {"UNDEF", LTYPE0, i386.AUNDEF},
+       {"ADDPD", LTYPE3, i386.AADDPD},
+       {"ADDPS", LTYPE3, i386.AADDPS},
+       {"ADDSD", LTYPE3, i386.AADDSD},
+       {"ADDSS", LTYPE3, i386.AADDSS},
+       {"AESENC", LTYPE3, i386.AAESENC},
+       {"ANDNPD", LTYPE3, i386.AANDNPD},
+       {"ANDNPS", LTYPE3, i386.AANDNPS},
+       {"ANDPD", LTYPE3, i386.AANDPD},
+       {"ANDPS", LTYPE3, i386.AANDPS},
+       {"CMPPD", LTYPEXC, i386.ACMPPD},
+       {"CMPPS", LTYPEXC, i386.ACMPPS},
+       {"CMPSD", LTYPEXC, i386.ACMPSD},
+       {"CMPSS", LTYPEXC, i386.ACMPSS},
+       {"COMISD", LTYPE3, i386.ACOMISD},
+       {"COMISS", LTYPE3, i386.ACOMISS},
+       {"CVTPL2PD", LTYPE3, i386.ACVTPL2PD},
+       {"CVTPL2PS", LTYPE3, i386.ACVTPL2PS},
+       {"CVTPD2PL", LTYPE3, i386.ACVTPD2PL},
+       {"CVTPD2PS", LTYPE3, i386.ACVTPD2PS},
+       {"CVTPS2PL", LTYPE3, i386.ACVTPS2PL},
+       {"CVTPS2PD", LTYPE3, i386.ACVTPS2PD},
+       {"CVTSD2SL", LTYPE3, i386.ACVTSD2SL},
+       {"CVTSD2SS", LTYPE3, i386.ACVTSD2SS},
+       {"CVTSL2SD", LTYPE3, i386.ACVTSL2SD},
+       {"CVTSL2SS", LTYPE3, i386.ACVTSL2SS},
+       {"CVTSS2SD", LTYPE3, i386.ACVTSS2SD},
+       {"CVTSS2SL", LTYPE3, i386.ACVTSS2SL},
+       {"CVTTPD2PL", LTYPE3, i386.ACVTTPD2PL},
+       {"CVTTPS2PL", LTYPE3, i386.ACVTTPS2PL},
+       {"CVTTSD2SL", LTYPE3, i386.ACVTTSD2SL},
+       {"CVTTSS2SL", LTYPE3, i386.ACVTTSS2SL},
+       {"DIVPD", LTYPE3, i386.ADIVPD},
+       {"DIVPS", LTYPE3, i386.ADIVPS},
+       {"DIVSD", LTYPE3, i386.ADIVSD},
+       {"DIVSS", LTYPE3, i386.ADIVSS},
+       {"MASKMOVOU", LTYPE3, i386.AMASKMOVOU},
+       {"MASKMOVDQU", LTYPE3, i386.AMASKMOVOU}, /* syn */
+       {"MAXPD", LTYPE3, i386.AMAXPD},
+       {"MAXPS", LTYPE3, i386.AMAXPS},
+       {"MAXSD", LTYPE3, i386.AMAXSD},
+       {"MAXSS", LTYPE3, i386.AMAXSS},
+       {"MINPD", LTYPE3, i386.AMINPD},
+       {"MINPS", LTYPE3, i386.AMINPS},
+       {"MINSD", LTYPE3, i386.AMINSD},
+       {"MINSS", LTYPE3, i386.AMINSS},
+       {"MOVAPD", LTYPE3, i386.AMOVAPD},
+       {"MOVAPS", LTYPE3, i386.AMOVAPS},
+       {"MOVO", LTYPE3, i386.AMOVO},
+       {"MOVOA", LTYPE3, i386.AMOVO}, /* syn */
+       {"MOVOU", LTYPE3, i386.AMOVOU},
+       {"MOVHLPS", LTYPE3, i386.AMOVHLPS},
+       {"MOVHPD", LTYPE3, i386.AMOVHPD},
+       {"MOVHPS", LTYPE3, i386.AMOVHPS},
+       {"MOVLHPS", LTYPE3, i386.AMOVLHPS},
+       {"MOVLPD", LTYPE3, i386.AMOVLPD},
+       {"MOVLPS", LTYPE3, i386.AMOVLPS},
+       {"MOVMSKPD", LTYPE3, i386.AMOVMSKPD},
+       {"MOVMSKPS", LTYPE3, i386.AMOVMSKPS},
+       {"MOVNTO", LTYPE3, i386.AMOVNTO},
+       {"MOVNTDQ", LTYPE3, i386.AMOVNTO}, /* syn */
+       {"MOVNTPD", LTYPE3, i386.AMOVNTPD},
+       {"MOVNTPS", LTYPE3, i386.AMOVNTPS},
+       {"MOVSD", LTYPE3, i386.AMOVSD},
+       {"MOVSS", LTYPE3, i386.AMOVSS},
+       {"MOVUPD", LTYPE3, i386.AMOVUPD},
+       {"MOVUPS", LTYPE3, i386.AMOVUPS},
+       {"MULPD", LTYPE3, i386.AMULPD},
+       {"MULPS", LTYPE3, i386.AMULPS},
+       {"MULSD", LTYPE3, i386.AMULSD},
+       {"MULSS", LTYPE3, i386.AMULSS},
+       {"ORPD", LTYPE3, i386.AORPD},
+       {"ORPS", LTYPE3, i386.AORPS},
+       {"PADDQ", LTYPE3, i386.APADDQ},
+       {"PAND", LTYPE3, i386.APAND},
+       {"PCMPEQB", LTYPE3, i386.APCMPEQB},
+       {"PMAXSW", LTYPE3, i386.APMAXSW},
+       {"PMAXUB", LTYPE3, i386.APMAXUB},
+       {"PMINSW", LTYPE3, i386.APMINSW},
+       {"PMINUB", LTYPE3, i386.APMINUB},
+       {"PMOVMSKB", LTYPE3, i386.APMOVMSKB},
+       {"PSADBW", LTYPE3, i386.APSADBW},
+       {"PSHUFB", LTYPE3, i386.APSHUFB},
+       {"PSHUFHW", LTYPEX, i386.APSHUFHW},
+       {"PSHUFL", LTYPEX, i386.APSHUFL},
+       {"PSHUFLW", LTYPEX, i386.APSHUFLW},
+       {"PSUBB", LTYPE3, i386.APSUBB},
+       {"PSUBL", LTYPE3, i386.APSUBL},
+       {"PSUBQ", LTYPE3, i386.APSUBQ},
+       {"PSUBSB", LTYPE3, i386.APSUBSB},
+       {"PSUBSW", LTYPE3, i386.APSUBSW},
+       {"PSUBUSB", LTYPE3, i386.APSUBUSB},
+       {"PSUBUSW", LTYPE3, i386.APSUBUSW},
+       {"PSUBW", LTYPE3, i386.APSUBW},
+       {"PUNPCKHQDQ", LTYPE3, i386.APUNPCKHQDQ},
+       {"PUNPCKLQDQ", LTYPE3, i386.APUNPCKLQDQ},
+       {"PXOR", LTYPE3, i386.APXOR},
+       {"RCPPS", LTYPE3, i386.ARCPPS},
+       {"RCPSS", LTYPE3, i386.ARCPSS},
+       {"RSQRTPS", LTYPE3, i386.ARSQRTPS},
+       {"RSQRTSS", LTYPE3, i386.ARSQRTSS},
+       {"SQRTPD", LTYPE3, i386.ASQRTPD},
+       {"SQRTPS", LTYPE3, i386.ASQRTPS},
+       {"SQRTSD", LTYPE3, i386.ASQRTSD},
+       {"SQRTSS", LTYPE3, i386.ASQRTSS},
+       {"SUBPD", LTYPE3, i386.ASUBPD},
+       {"SUBPS", LTYPE3, i386.ASUBPS},
+       {"SUBSD", LTYPE3, i386.ASUBSD},
+       {"SUBSS", LTYPE3, i386.ASUBSS},
+       {"UCOMISD", LTYPE3, i386.AUCOMISD},
+       {"UCOMISS", LTYPE3, i386.AUCOMISS},
+       {"UNPCKHPD", LTYPE3, i386.AUNPCKHPD},
+       {"UNPCKHPS", LTYPE3, i386.AUNPCKHPS},
+       {"UNPCKLPD", LTYPE3, i386.AUNPCKLPD},
+       {"UNPCKLPS", LTYPE3, i386.AUNPCKLPS},
+       {"XORPD", LTYPE3, i386.AXORPD},
+       {"XORPS", LTYPE3, i386.AXORPS},
+       {"USEFIELD", LTYPEN, i386.AUSEFIELD},
+       {"PCDATA", LTYPEPC, i386.APCDATA},
+       {"FUNCDATA", LTYPEF, i386.AFUNCDATA},
+}
+
+func cinit() {
+       nullgen.Type = i386.D_NONE
+       nullgen.Index = i386.D_NONE
+}
+
+func checkscale(scale int8) {
+       switch scale {
+       case 1,
+               2,
+               4,
+               8:
+               return
+       }
+
+       yyerror("scale must be 1248: %d", scale)
+}
+
+func syminit(s *asm.Sym) {
+       s.Type = LNAME
+       s.Value = 0
+}
+
+func cclean() {
+       var g2 Addr2
+
+       g2.from = nullgen
+       g2.to = nullgen
+       outcode(i386.AEND, &g2)
+}
+
+var lastpc *obj.Prog
+
+type Addr2 struct {
+       from obj.Addr
+       to   obj.Addr
+}
+
+func outcode(a int, g2 *Addr2) {
+       var p *obj.Prog
+       var pl *obj.Plist
+
+       if asm.Pass == 1 {
+               goto out
+       }
+
+       p = new(obj.Prog)
+       *p = obj.Prog{}
+       p.Ctxt = asm.Ctxt
+       p.As = int16(a)
+       p.Lineno = stmtline
+       p.From = g2.from
+       p.To = g2.to
+       p.Pc = int64(asm.PC)
+
+       if lastpc == nil {
+               pl = obj.Linknewplist(asm.Ctxt)
+               pl.Firstpc = p
+       } else {
+
+               lastpc.Link = p
+       }
+       lastpc = p
+
+out:
+       if a != i386.AGLOBL && a != i386.ADATA {
+               asm.PC++
+       }
+}
diff --git a/src/cmd/new8a/y.go b/src/cmd/new8a/y.go
new file mode 100644 (file)
index 0000000..b286f53
--- /dev/null
@@ -0,0 +1,1306 @@
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/i386"
+)
+
+//line a.y:41
+type yySymType struct {
+       yys  int
+       sym  *asm.Sym
+       lval int64
+       con2 struct {
+               v1 int32
+               v2 int32
+       }
+       dval  float64
+       sval  string
+       addr  obj.Addr
+       addr2 Addr2
+}
+
+const LTYPE0 = 57346
+const LTYPE1 = 57347
+const LTYPE2 = 57348
+const LTYPE3 = 57349
+const LTYPE4 = 57350
+const LTYPEC = 57351
+const LTYPED = 57352
+const LTYPEN = 57353
+const LTYPER = 57354
+const LTYPET = 57355
+const LTYPES = 57356
+const LTYPEM = 57357
+const LTYPEI = 57358
+const LTYPEG = 57359
+const LTYPEXC = 57360
+const LTYPEX = 57361
+const LTYPEPC = 57362
+const LTYPEF = 57363
+const LCONST = 57364
+const LFP = 57365
+const LPC = 57366
+const LSB = 57367
+const LBREG = 57368
+const LLREG = 57369
+const LSREG = 57370
+const LFREG = 57371
+const LXREG = 57372
+const LFCONST = 57373
+const LSCONST = 57374
+const LSP = 57375
+const LNAME = 57376
+const LLAB = 57377
+const LVAR = 57378
+
+var yyToknames = []string{
+       "'|'",
+       "'^'",
+       "'&'",
+       "'<'",
+       "'>'",
+       "'+'",
+       "'-'",
+       "'*'",
+       "'/'",
+       "'%'",
+       "LTYPE0",
+       "LTYPE1",
+       "LTYPE2",
+       "LTYPE3",
+       "LTYPE4",
+       "LTYPEC",
+       "LTYPED",
+       "LTYPEN",
+       "LTYPER",
+       "LTYPET",
+       "LTYPES",
+       "LTYPEM",
+       "LTYPEI",
+       "LTYPEG",
+       "LTYPEXC",
+       "LTYPEX",
+       "LTYPEPC",
+       "LTYPEF",
+       "LCONST",
+       "LFP",
+       "LPC",
+       "LSB",
+       "LBREG",
+       "LLREG",
+       "LSREG",
+       "LFREG",
+       "LXREG",
+       "LFCONST",
+       "LSCONST",
+       "LSP",
+       "LNAME",
+       "LLAB",
+       "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+       -1, 1,
+       1, -1,
+       -2, 2,
+}
+
+const yyNprod = 132
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 586
+
+var yyAct = []int{
+
+       47, 37, 59, 185, 45, 120, 80, 3, 49, 78,
+       60, 187, 268, 57, 267, 69, 208, 68, 85, 82,
+       84, 67, 83, 169, 73, 100, 62, 102, 46, 109,
+       266, 115, 109, 92, 94, 96, 262, 255, 253, 104,
+       106, 241, 239, 237, 221, 219, 81, 210, 209, 109,
+       170, 240, 234, 117, 118, 119, 231, 207, 211, 173,
+       108, 125, 144, 110, 168, 135, 116, 69, 112, 126,
+       230, 229, 109, 133, 53, 52, 136, 223, 85, 82,
+       84, 142, 83, 222, 143, 153, 152, 139, 141, 151,
+       58, 150, 145, 149, 148, 53, 52, 50, 147, 146,
+       138, 36, 113, 134, 64, 132, 81, 131, 114, 36,
+       124, 51, 33, 31, 30, 154, 71, 29, 50, 54,
+       27, 228, 28, 175, 176, 227, 111, 220, 165, 167,
+       109, 117, 51, 55, 166, 69, 247, 71, 184, 186,
+       54, 182, 142, 246, 183, 143, 181, 165, 167, 236,
+       192, 172, 191, 166, 251, 252, 109, 109, 109, 109,
+       109, 256, 183, 109, 109, 109, 195, 196, 263, 257,
+       212, 226, 217, 245, 215, 53, 130, 137, 34, 117,
+       218, 111, 216, 38, 260, 259, 32, 197, 198, 199,
+       200, 201, 254, 225, 204, 205, 206, 89, 50, 121,
+       75, 122, 123, 109, 109, 88, 98, 128, 127, 235,
+       55, 213, 51, 258, 238, 122, 123, 129, 203, 244,
+       54, 174, 180, 202, 6, 242, 107, 243, 157, 158,
+       159, 249, 248, 250, 232, 233, 2, 188, 189, 190,
+       1, 193, 194, 105, 39, 41, 44, 40, 42, 103,
+       7, 43, 101, 99, 97, 261, 95, 93, 91, 87,
+       264, 265, 9, 10, 11, 12, 13, 17, 15, 18,
+       14, 16, 19, 20, 21, 22, 23, 24, 25, 26,
+       53, 52, 79, 163, 162, 160, 161, 155, 156, 157,
+       158, 159, 4, 76, 8, 74, 5, 72, 63, 61,
+       53, 52, 140, 50, 56, 65, 224, 39, 41, 44,
+       40, 42, 214, 0, 43, 86, 0, 51, 0, 0,
+       0, 77, 48, 50, 60, 54, 0, 39, 41, 44,
+       40, 42, 53, 52, 43, 86, 0, 51, 0, 0,
+       0, 0, 48, 0, 60, 54, 155, 156, 157, 158,
+       159, 0, 53, 52, 0, 50, 0, 0, 0, 39,
+       41, 44, 40, 42, 0, 0, 43, 55, 0, 51,
+       0, 0, 53, 52, 48, 50, 60, 54, 0, 39,
+       41, 44, 40, 42, 0, 0, 43, 55, 0, 51,
+       0, 0, 0, 90, 48, 50, 0, 54, 0, 39,
+       41, 44, 40, 42, 53, 52, 43, 55, 0, 51,
+       0, 0, 0, 35, 48, 0, 0, 54, 0, 0,
+       53, 52, 0, 0, 53, 52, 0, 50, 0, 0,
+       0, 39, 41, 44, 40, 42, 0, 0, 43, 55,
+       0, 51, 0, 50, 53, 52, 48, 50, 0, 54,
+       0, 39, 41, 44, 40, 42, 0, 51, 43, 53,
+       52, 51, 71, 0, 60, 54, 48, 50, 0, 54,
+       164, 163, 162, 160, 161, 155, 156, 157, 158, 159,
+       0, 51, 50, 0, 53, 52, 71, 0, 187, 54,
+       53, 52, 0, 0, 70, 0, 51, 0, 0, 0,
+       66, 71, 0, 60, 54, 53, 178, 50, 0, 0,
+       0, 53, 52, 50, 0, 53, 52, 0, 171, 70,
+       0, 51, 179, 0, 0, 0, 71, 51, 50, 54,
+       0, 0, 71, 0, 50, 54, 0, 177, 50, 0,
+       0, 0, 51, 0, 0, 0, 55, 71, 51, 0,
+       54, 0, 51, 48, 0, 0, 54, 71, 0, 0,
+       54, 164, 163, 162, 160, 161, 155, 156, 157, 158,
+       159, 162, 160, 161, 155, 156, 157, 158, 159, 160,
+       161, 155, 156, 157, 158, 159,
+}
+var yyPact = []int{
+
+       -1000, -1000, 248, -1000, 73, -1000, 69, 66, 64, 62,
+       363, 323, 323, 395, 450, 89, 502, 271, 343, 323,
+       323, 323, 502, 208, -43, 323, 323, -1000, 506, -1000,
+       -1000, 506, -1000, -1000, -1000, 395, -1000, -1000, -1000, -1000,
+       -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17, 65, 15,
+       -1000, -1000, 506, 506, 506, 192, -1000, 60, -1000, -1000,
+       166, -1000, 57, -1000, 55, -1000, 475, -1000, 53, 14,
+       206, 506, -1000, 165, -1000, 50, -1000, 291, -1000, 395,
+       -1000, -1000, -1000, -1000, -1000, 11, 192, -1000, -1000, -1000,
+       395, -1000, 49, -1000, 48, -1000, 44, -1000, 43, -1000,
+       41, -1000, 39, -1000, 36, -1000, 35, 248, 557, -1000,
+       557, -1000, 91, 12, -2, 466, 114, -1000, -1000, -1000,
+       8, 213, 506, 506, -1000, -1000, -1000, -1000, -1000, 496,
+       481, 395, 323, -1000, 475, 128, -1000, 506, 435, -1000,
+       415, -1000, -1000, -1000, 110, 8, 395, 395, 395, 411,
+       395, 395, 323, 323, -1000, 506, 506, 506, 506, 506,
+       216, 210, 506, 506, 506, 5, -4, -5, 7, 506,
+       -1000, -1000, 200, 139, 206, -1000, -1000, -7, 86, -1000,
+       -1000, -1000, -1000, -8, 33, -1000, 27, 161, 78, 74,
+       -1000, -1000, 21, 20, 6, -1000, -1000, 217, 217, -1000,
+       -1000, -1000, 506, 506, 572, 565, 278, 1, 506, -1000,
+       -1000, 112, -9, 506, -10, -1000, -1000, -1000, 0, -1000,
+       -11, -1000, -43, -42, -1000, 209, 141, 106, 98, -43,
+       506, 208, 337, 337, 117, -14, 181, -1000, -15, -1000,
+       126, -1000, -1000, -1000, 137, 203, -1000, -1000, -1000, -1000,
+       -1000, 174, 173, -1000, 506, -1000, -16, -1000, 136, 506,
+       506, -22, -1000, -1000, -38, -40, -1000, -1000, -1000,
+}
+var yyPgo = []int{
+
+       0, 0, 31, 312, 5, 306, 183, 2, 3, 1,
+       8, 6, 90, 13, 9, 4, 28, 186, 305, 178,
+       304, 299, 298, 297, 295, 293, 259, 258, 257, 256,
+       254, 253, 252, 249, 243, 240, 236, 7, 226, 224,
+}
+var yyR1 = []int{
+
+       0, 35, 36, 35, 38, 37, 37, 37, 37, 39,
+       39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+       39, 39, 39, 39, 39, 39, 39, 39, 39, 17,
+       17, 21, 22, 20, 20, 19, 19, 18, 18, 18,
+       23, 24, 24, 25, 25, 25, 26, 26, 27, 27,
+       28, 28, 29, 29, 29, 30, 30, 31, 32, 33,
+       34, 12, 12, 14, 14, 14, 14, 14, 14, 14,
+       13, 13, 11, 11, 9, 9, 9, 9, 9, 9,
+       7, 7, 7, 7, 7, 7, 7, 8, 5, 5,
+       5, 5, 6, 6, 15, 15, 15, 15, 15, 15,
+       15, 15, 15, 15, 15, 16, 16, 10, 10, 4,
+       4, 4, 3, 3, 3, 1, 1, 1, 1, 1,
+       1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       2, 2,
+}
+var yyR2 = []int{
+
+       0, 0, 0, 3, 0, 4, 1, 2, 2, 3,
+       3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+       1, 3, 3, 2, 1, 2, 1, 2, 1, 3,
+       5, 3, 5, 2, 1, 2, 1, 1, 3, 5,
+       3, 5, 2, 1, 3, 3, 5, 5, 5, 3,
+       3, 1, 1, 1, 1, 2, 2, 1, 1, 1,
+       1, 1, 4, 2, 1, 1, 1, 1, 1, 1,
+       2, 2, 2, 2, 4, 5, 3, 2, 1, 2,
+       3, 4, 1, 1, 1, 4, 4, 6, 9, 9,
+       3, 3, 4, 5, 8, 1, 6, 5, 7, 0,
+       2, 2, 1, 1, 1, 1, 1, 2, 2, 2,
+       3, 1, 3, 3, 3, 3, 3, 4, 4, 3,
+       3, 3,
+}
+var yyChk = []int{
+
+       -1000, -35, -36, -37, 44, 48, -39, 2, 46, 14,
+       15, 16, 17, 18, 22, 20, 23, 19, 21, 24,
+       25, 26, 27, 28, 29, 30, 31, 47, 49, 48,
+       48, 49, -17, 50, -19, 50, -12, -9, -6, 36,
+       39, 37, 40, 43, 38, -15, -16, -1, 51, -10,
+       32, 46, 10, 9, 54, 44, -20, -13, -12, -7,
+       53, -21, -13, -22, -12, -18, 50, -11, -7, -1,
+       44, 51, -23, -10, -24, -6, -25, 50, -14, 11,
+       -11, -16, -9, -15, -7, -1, 44, -26, -17, -19,
+       50, -27, -13, -28, -13, -29, -13, -30, -6, -31,
+       -9, -32, -7, -33, -13, -34, -13, -38, -2, -1,
+       -2, -12, 51, 37, 43, -2, 51, -1, -1, -1,
+       -4, 7, 9, 10, 50, -1, -10, 42, 41, 51,
+       10, 50, 50, -11, 50, 51, -4, 12, 50, -14,
+       11, -10, -9, -15, 51, -4, 50, 50, 50, 50,
+       50, 50, 50, 50, -37, 9, 10, 11, 12, 13,
+       7, 8, 6, 5, 4, 37, 43, 38, 52, 11,
+       52, 52, 37, 51, 8, -1, -1, 41, 10, 41,
+       -12, -13, -11, 34, -1, -8, -1, 53, -12, -12,
+       -12, -7, -1, -12, -12, -13, -13, -2, -2, -2,
+       -2, -2, 7, 8, -2, -2, -2, 52, 11, 52,
+       52, 51, -1, 11, -3, 35, 43, 33, -4, 52,
+       41, 52, 50, 50, -5, 32, 10, 47, 47, 50,
+       50, 50, -2, -2, 51, -1, 37, 52, -1, 52,
+       51, 52, -7, -8, 10, 32, 37, 38, -7, -1,
+       -9, 37, 38, 52, 11, 52, 35, 32, 10, 11,
+       11, -1, 52, 32, -1, -1, 52, 52, 52,
+}
+var yyDef = []int{
+
+       1, -2, 0, 3, 0, 6, 0, 0, 0, 29,
+       0, 0, 0, 0, 0, 0, 0, 0, 29, 0,
+       0, 0, 0, 0, 0, 0, 0, 4, 0, 7,
+       8, 0, 11, 30, 12, 0, 36, 61, 62, 74,
+       75, 76, 77, 78, 79, 92, 93, 94, 0, 105,
+       115, 116, 0, 0, 0, 109, 13, 34, 70, 71,
+       0, 14, 0, 15, 0, 16, 0, 38, 0, 0,
+       109, 0, 17, 0, 18, 0, 19, 0, 44, 0,
+       63, 64, 67, 68, 69, 94, 109, 20, 46, 47,
+       30, 21, 0, 22, 0, 23, 53, 24, 0, 25,
+       0, 26, 0, 27, 0, 28, 0, 0, 9, 121,
+       10, 35, 0, 0, 0, 0, 0, 117, 118, 119,
+       0, 0, 0, 0, 33, 80, 81, 82, 83, 0,
+       0, 0, 0, 37, 0, 0, 73, 0, 0, 43,
+       0, 45, 65, 66, 0, 73, 0, 0, 52, 0,
+       0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 100, 0,
+       101, 120, 0, 0, 109, 110, 111, 0, 0, 86,
+       31, 32, 39, 0, 0, 41, 0, 0, 48, 50,
+       54, 55, 0, 0, 0, 59, 60, 122, 123, 124,
+       125, 126, 0, 0, 129, 130, 131, 95, 0, 96,
+       102, 0, 0, 0, 0, 112, 113, 114, 0, 84,
+       0, 72, 0, 0, 87, 88, 0, 0, 0, 0,
+       0, 0, 127, 128, 0, 0, 0, 103, 0, 107,
+       0, 85, 40, 42, 0, 89, 49, 51, 56, 57,
+       58, 0, 0, 97, 0, 106, 0, 90, 0, 0,
+       0, 0, 108, 91, 0, 0, 104, 98, 99,
+}
+var yyTok1 = []int{
+
+       1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 53, 13, 6, 3,
+       51, 52, 11, 9, 50, 10, 3, 12, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 47, 48,
+       7, 49, 8, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 4, 3, 54,
+}
+var yyTok2 = []int{
+
+       2, 3, 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,
+}
+var yyTok3 = []int{
+       0,
+}
+
+//line yaccpar:1
+
+/*     parser for yacc output  */
+
+var yyDebug = 0
+
+type yyLexer interface {
+       Lex(lval *yySymType) int
+       Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+       // 4 is TOKSTART above
+       if c >= 4 && c-4 < len(yyToknames) {
+               if yyToknames[c-4] != "" {
+                       return yyToknames[c-4]
+               }
+       }
+       return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+       if s >= 0 && s < len(yyStatenames) {
+               if yyStatenames[s] != "" {
+                       return yyStatenames[s]
+               }
+       }
+       return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+       c := 0
+       char := lex.Lex(lval)
+       if char <= 0 {
+               c = yyTok1[0]
+               goto out
+       }
+       if char < len(yyTok1) {
+               c = yyTok1[char]
+               goto out
+       }
+       if char >= yyPrivate {
+               if char < yyPrivate+len(yyTok2) {
+                       c = yyTok2[char-yyPrivate]
+                       goto out
+               }
+       }
+       for i := 0; i < len(yyTok3); i += 2 {
+               c = yyTok3[i+0]
+               if c == char {
+                       c = yyTok3[i+1]
+                       goto out
+               }
+       }
+
+out:
+       if c == 0 {
+               c = yyTok2[1] /* unknown char */
+       }
+       if yyDebug >= 3 {
+               __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+       }
+       return c
+}
+
+func yyParse(yylex yyLexer) int {
+       var yyn int
+       var yylval yySymType
+       var yyVAL yySymType
+       yyS := make([]yySymType, yyMaxDepth)
+
+       Nerrs := 0   /* number of errors */
+       Errflag := 0 /* error recovery flag */
+       yystate := 0
+       yychar := -1
+       yyp := -1
+       goto yystack
+
+ret0:
+       return 0
+
+ret1:
+       return 1
+
+yystack:
+       /* put a state and value onto the stack */
+       if yyDebug >= 4 {
+               __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+       }
+
+       yyp++
+       if yyp >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyS[yyp] = yyVAL
+       yyS[yyp].yys = yystate
+
+yynewstate:
+       yyn = yyPact[yystate]
+       if yyn <= yyFlag {
+               goto yydefault /* simple state */
+       }
+       if yychar < 0 {
+               yychar = yylex1(yylex, &yylval)
+       }
+       yyn += yychar
+       if yyn < 0 || yyn >= yyLast {
+               goto yydefault
+       }
+       yyn = yyAct[yyn]
+       if yyChk[yyn] == yychar { /* valid shift */
+               yychar = -1
+               yyVAL = yylval
+               yystate = yyn
+               if Errflag > 0 {
+                       Errflag--
+               }
+               goto yystack
+       }
+
+yydefault:
+       /* default state action */
+       yyn = yyDef[yystate]
+       if yyn == -2 {
+               if yychar < 0 {
+                       yychar = yylex1(yylex, &yylval)
+               }
+
+               /* look through exception table */
+               xi := 0
+               for {
+                       if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+                               break
+                       }
+                       xi += 2
+               }
+               for xi += 2; ; xi += 2 {
+                       yyn = yyExca[xi+0]
+                       if yyn < 0 || yyn == yychar {
+                               break
+                       }
+               }
+               yyn = yyExca[xi+1]
+               if yyn < 0 {
+                       goto ret0
+               }
+       }
+       if yyn == 0 {
+               /* error ... attempt to resume parsing */
+               switch Errflag {
+               case 0: /* brand new error */
+                       yylex.Error("syntax error")
+                       Nerrs++
+                       if yyDebug >= 1 {
+                               __yyfmt__.Printf("%s", yyStatname(yystate))
+                               __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+                       }
+                       fallthrough
+
+               case 1, 2: /* incompletely recovered error ... try again */
+                       Errflag = 3
+
+                       /* find a state where "error" is a legal shift action */
+                       for yyp >= 0 {
+                               yyn = yyPact[yyS[yyp].yys] + yyErrCode
+                               if yyn >= 0 && yyn < yyLast {
+                                       yystate = yyAct[yyn] /* simulate a shift of "error" */
+                                       if yyChk[yystate] == yyErrCode {
+                                               goto yystack
+                                       }
+                               }
+
+                               /* the current p has no shift on "error", pop stack */
+                               if yyDebug >= 2 {
+                                       __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+                               }
+                               yyp--
+                       }
+                       /* there is no state on the stack with an error shift ... abort */
+                       goto ret1
+
+               case 3: /* no shift yet; clobber input char */
+                       if yyDebug >= 2 {
+                               __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+                       }
+                       if yychar == yyEofCode {
+                               goto ret1
+                       }
+                       yychar = -1
+                       goto yynewstate /* try again in the same state */
+               }
+       }
+
+       /* reduction by production yyn */
+       if yyDebug >= 2 {
+               __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+       }
+
+       yynt := yyn
+       yypt := yyp
+       _ = yypt // guard against "declared and not used"
+
+       yyp -= yyR2[yyn]
+       // yyp is now the index of $0. Perform the default action. Iff the
+       // reduced production is Îµ, $1 is possibly out of range.
+       if yyp+1 >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyVAL = yyS[yyp+1]
+
+       /* consult goto table to find next state */
+       yyn = yyR1[yyn]
+       yyg := yyPgo[yyn]
+       yyj := yyg + yyS[yyp].yys + 1
+
+       if yyj >= yyLast {
+               yystate = yyAct[yyg]
+       } else {
+               yystate = yyAct[yyj]
+               if yyChk[yystate] != -yyn {
+                       yystate = yyAct[yyg]
+               }
+       }
+       // dummy call; replaced with literal code
+       switch yynt {
+
+       case 2:
+               //line a.y:75
+               {
+                       stmtline = asm.Lineno
+               }
+       case 4:
+               //line a.y:82
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+                               yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyS[yypt-1].sym.Type = LLAB
+                       yyS[yypt-1].sym.Value = int64(asm.PC)
+               }
+       case 9:
+               //line a.y:97
+               {
+                       yyS[yypt-2].sym.Type = LVAR
+                       yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+               }
+       case 10:
+               //line a.y:102
+               {
+                       if yyS[yypt-2].sym.Value != int64(yyS[yypt-0].lval) {
+                               yyerror("redeclaration of %s", yyS[yypt-2].sym.Name)
+                       }
+                       yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+               }
+       case 11:
+               //line a.y:108
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 12:
+               //line a.y:109
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 13:
+               //line a.y:110
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 14:
+               //line a.y:111
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 15:
+               //line a.y:112
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 16:
+               //line a.y:113
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 17:
+               //line a.y:114
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 18:
+               //line a.y:115
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 19:
+               //line a.y:116
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 20:
+               //line a.y:117
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 21:
+               //line a.y:118
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 22:
+               //line a.y:119
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 23:
+               //line a.y:120
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 24:
+               //line a.y:121
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 25:
+               //line a.y:122
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 26:
+               //line a.y:123
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 27:
+               //line a.y:124
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 28:
+               //line a.y:125
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+               }
+       case 29:
+               //line a.y:128
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = nullgen
+               }
+       case 30:
+               //line a.y:133
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = nullgen
+               }
+       case 31:
+               //line a.y:140
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 32:
+               //line a.y:147
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 33:
+               //line a.y:154
+               {
+                       yyVAL.addr2.from = yyS[yypt-1].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 34:
+               //line a.y:159
+               {
+                       yyVAL.addr2.from = yyS[yypt-0].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 35:
+               //line a.y:166
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 36:
+               //line a.y:171
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 37:
+               //line a.y:178
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 38:
+               //line a.y:183
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 39:
+               //line a.y:188
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 40:
+               //line a.y:195
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 41:
+               //line a.y:203
+               {
+                       asm.Settext(yyS[yypt-2].addr.Sym)
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 42:
+               //line a.y:209
+               {
+                       asm.Settext(yyS[yypt-4].addr.Sym)
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 43:
+               //line a.y:218
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 44:
+               //line a.y:223
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 45:
+               //line a.y:228
+               {
+                       yyVAL.addr2.from = nullgen
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+                       yyVAL.addr2.to.Index = uint8(yyS[yypt-0].addr.Type)
+                       yyVAL.addr2.to.Type = D_INDIR + D_ADDR
+               }
+       case 46:
+               yyVAL.addr2 = yyS[yypt-0].addr2
+       case 47:
+               yyVAL.addr2 = yyS[yypt-0].addr2
+       case 48:
+               //line a.y:241
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 49:
+               //line a.y:246
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       if yyVAL.addr2.from.Index != D_NONE {
+                               yyerror("dp shift with lhs index")
+                       }
+                       yyVAL.addr2.from.Index = uint8(yyS[yypt-0].lval)
+               }
+       case 50:
+               //line a.y:257
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 51:
+               //line a.y:262
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       if yyVAL.addr2.to.Index != D_NONE {
+                               yyerror("dp move with lhs index")
+                       }
+                       yyVAL.addr2.to.Index = uint8(yyS[yypt-0].lval)
+               }
+       case 52:
+               //line a.y:273
+               {
+                       yyVAL.addr2.from = yyS[yypt-1].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 53:
+               //line a.y:278
+               {
+                       yyVAL.addr2.from = yyS[yypt-0].addr
+                       yyVAL.addr2.to = nullgen
+               }
+       case 54:
+               //line a.y:283
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 55:
+               //line a.y:290
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 56:
+               //line a.y:295
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 57:
+               //line a.y:303
+               {
+                       yyVAL.addr2.from = yyS[yypt-4].addr
+                       yyVAL.addr2.to = yyS[yypt-2].addr
+                       yyVAL.addr2.to.Offset = yyS[yypt-0].lval
+               }
+       case 58:
+               //line a.y:311
+               {
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+                       if yyS[yypt-4].addr.Type != D_CONST {
+                               yyerror("illegal constant")
+                       }
+                       yyVAL.addr2.to.Offset = yyS[yypt-4].addr.Offset
+               }
+       case 59:
+               //line a.y:322
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+                               yyerror("arguments to PCDATA must be integer constants")
+                       }
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 60:
+               //line a.y:332
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST {
+                               yyerror("index for FUNCDATA must be integer constant")
+                       }
+                       if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC {
+                               yyerror("value for FUNCDATA must be symbol reference")
+                       }
+                       yyVAL.addr2.from = yyS[yypt-2].addr
+                       yyVAL.addr2.to = yyS[yypt-0].addr
+               }
+       case 61:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 62:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 63:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 64:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 65:
+               //line a.y:351
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 66:
+               //line a.y:355
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 67:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 68:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 69:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 70:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 71:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 72:
+               //line a.y:368
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+               }
+       case 73:
+               //line a.y:374
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       yyVAL.addr = nullgen
+                       if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+                               yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+               }
+       case 74:
+               //line a.y:386
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 75:
+               //line a.y:391
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 76:
+               //line a.y:396
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 77:
+               //line a.y:401
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 78:
+               //line a.y:406
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SP
+               }
+       case 79:
+               //line a.y:411
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+               }
+       case 80:
+               //line a.y:418
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 81:
+               //line a.y:424
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       yyVAL.addr.Index = uint8(yyS[yypt-0].addr.Type)
+                       yyVAL.addr.Type = D_ADDR
+                       /*
+                               if($2.Type == D_AUTO || $2.Type == D_PARAM)
+                                       yyerror("constant cannot be automatic: %s",
+                                               $2.Sym.name);
+                       */
+               }
+       case 82:
+               //line a.y:434
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SCONST
+                       yyVAL.addr.U.Sval = yyS[yypt-0].sval
+               }
+       case 83:
+               //line a.y:440
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-0].dval
+               }
+       case 84:
+               //line a.y:446
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-1].dval
+               }
+       case 85:
+               //line a.y:452
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-1].dval
+               }
+       case 86:
+               //line a.y:458
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+               }
+       case 87:
+               //line a.y:466
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST2
+                       yyVAL.addr.Offset = int64(yyS[yypt-0].con2.v1)
+                       yyVAL.addr.Offset2 = int32(yyS[yypt-0].con2.v2)
+               }
+       case 88:
+               //line a.y:475
+               {
+                       yyVAL.con2.v1 = int32(yyS[yypt-0].lval)
+                       yyVAL.con2.v2 = -obj.ArgsSizeUnknown
+               }
+       case 89:
+               //line a.y:480
+               {
+                       yyVAL.con2.v1 = int32(-yyS[yypt-0].lval)
+                       yyVAL.con2.v2 = -obj.ArgsSizeUnknown
+               }
+       case 90:
+               //line a.y:485
+               {
+                       yyVAL.con2.v1 = int32(yyS[yypt-2].lval)
+                       yyVAL.con2.v2 = int32(yyS[yypt-0].lval)
+               }
+       case 91:
+               //line a.y:490
+               {
+                       yyVAL.con2.v1 = int32(-yyS[yypt-2].lval)
+                       yyVAL.con2.v2 = int32(yyS[yypt-0].lval)
+               }
+       case 92:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 93:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 94:
+               //line a.y:501
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_INDIR + D_NONE
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 95:
+               //line a.y:507
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 96:
+               //line a.y:513
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_INDIR + D_SP
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 97:
+               //line a.y:519
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_INDIR + D_NONE
+                       yyVAL.addr.Offset = yyS[yypt-5].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 98:
+               //line a.y:528
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Offset = yyS[yypt-8].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 99:
+               //line a.y:537
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Offset = yyS[yypt-8].lval
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 100:
+               //line a.y:546
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+               }
+       case 101:
+               //line a.y:551
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_INDIR + D_SP
+               }
+       case 102:
+               //line a.y:556
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 103:
+               //line a.y:562
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_INDIR + D_NONE
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 104:
+               //line a.y:570
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 105:
+               //line a.y:580
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+               }
+       case 106:
+               //line a.y:584
+               {
+                       yyVAL.addr = yyS[yypt-5].addr
+                       yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       checkscale(yyVAL.addr.Scale)
+               }
+       case 107:
+               //line a.y:593
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 108:
+               //line a.y:600
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_STATIC
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 109:
+               //line a.y:608
+               {
+                       yyVAL.lval = 0
+               }
+       case 110:
+               //line a.y:612
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 111:
+               //line a.y:616
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 112:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 113:
+               //line a.y:623
+               {
+                       yyVAL.lval = D_AUTO
+               }
+       case 114:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 115:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 116:
+               //line a.y:631
+               {
+                       yyVAL.lval = yyS[yypt-0].sym.Value
+               }
+       case 117:
+               //line a.y:635
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 118:
+               //line a.y:639
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 119:
+               //line a.y:643
+               {
+                       yyVAL.lval = ^yyS[yypt-0].lval
+               }
+       case 120:
+               //line a.y:647
+               {
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 121:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 122:
+               //line a.y:654
+               {
+                       yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+               }
+       case 123:
+               //line a.y:658
+               {
+                       yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+               }
+       case 124:
+               //line a.y:662
+               {
+                       yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+               }
+       case 125:
+               //line a.y:666
+               {
+                       yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+               }
+       case 126:
+               //line a.y:670
+               {
+                       yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+               }
+       case 127:
+               //line a.y:674
+               {
+                       yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+               }
+       case 128:
+               //line a.y:678
+               {
+                       yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+               }
+       case 129:
+               //line a.y:682
+               {
+                       yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+               }
+       case 130:
+               //line a.y:686
+               {
+                       yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+               }
+       case 131:
+               //line a.y:690
+               {
+                       yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+               }
+       }
+       goto yystack /* stack new state and value */
+}
diff --git a/src/cmd/new9a/a.y b/src/cmd/new9a/a.y
new file mode 100644 (file)
index 0000000..cdc15fc
--- /dev/null
@@ -0,0 +1,1004 @@
+// 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.
+
+%{
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/ppc64"
+)
+%}
+
+%union
+{
+       sym *asm.Sym
+       lval int64
+       dval float64
+       sval string
+       addr obj.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:
+       LNAME ':'
+       {
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.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 = int($1);
+       }
+|      ';'
+|      inst ';'
+|      error ';'
+
+inst:
+/*
+ * load ints and bytes
+ */
+       LMOVW rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW addr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW regaddr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVB addr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVB regaddr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * load floats
+ */
+|      LFMOV addr ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFMOV regaddr ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFMOV fimm ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * store ints and bytes
+ */
+|      LMOVW rreg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * store floats
+ */
+|      LMOVW freg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW freg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * floating point status
+ */
+|      LMOVW fpscr ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW freg ','  fpscr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW freg ',' imm ',' fpscr
+       {
+               outgcode(int($1), &$2, NREG, &$4, &$6);
+       }
+|      LMOVW fpscr ',' creg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW imm ',' fpscrf
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMTFSB imm ',' con
+       {
+               outcode(int($1), &$2, int($4), &nullgen);
+       }
+/*
+ * field moves (mtcrf)
+ */
+|      LMOVW rreg ',' imm ',' lcr
+       {
+               outgcode(int($1), &$2, NREG, &$4, &$6);
+       }
+|      LMOVW rreg ',' creg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' lcr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * integer operations
+ * logical instructions
+ * shift instructions
+ * unary instructions
+ */
+|      LADDW rreg ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LADDW imm ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LADDW rreg ',' imm ',' rreg
+       {
+               outgcode(int($1), &$2, NREG, &$4, &$6);
+       }
+|      LADDW rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LADDW imm ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LLOGW rreg ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LLOGW rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LSHW rreg ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LSHW rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LSHW imm ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LSHW imm ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LABS rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LABS rreg
+       {
+               outcode(int($1), &$2, NREG, &$2);
+       }
+/*
+ * multiply-accumulate
+ */
+|      LMA rreg ',' sreg ',' rreg
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+/*
+ * move immediate: macro for cau+or, addi, addis, and other combinations
+ */
+|      LMOVW imm ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW ximm ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * condition register operations
+ */
+|      LCROP cbit ',' cbit
+       {
+               outcode(int($1), &$2, int($4.Reg), &$4);
+       }
+|      LCROP cbit ',' con ',' cbit
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+/*
+ * condition register moves
+ * move from machine state register
+ */
+|      LMOVW creg ',' creg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW psr ',' creg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW lcr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW psr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW xlreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' xlreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW creg ',' psr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' psr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * branch, branch conditional
+ * branch conditional register
+ * branch conditional to count register
+ */
+|      LBRA rel
+       {
+               outcode(int($1), &nullgen, NREG, &$2);
+       }
+|      LBRA addr
+       {
+               outcode(int($1), &nullgen, NREG, &$2);
+       }
+|      LBRA '(' xlreg ')'
+       {
+               outcode(int($1), &nullgen, NREG, &$3);
+       }
+|      LBRA ',' rel
+       {
+               outcode(int($1), &nullgen, NREG, &$3);
+       }
+|      LBRA ',' addr
+       {
+               outcode(int($1), &nullgen, NREG, &$3);
+       }
+|      LBRA ',' '(' xlreg ')'
+       {
+               outcode(int($1), &nullgen, NREG, &$4);
+       }
+|      LBRA creg ',' rel
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LBRA creg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LBRA creg ',' '(' xlreg ')'
+       {
+               outcode(int($1), &$2, NREG, &$5);
+       }
+|      LBRA con ',' rel
+       {
+               outcode(int($1), &nullgen, int($2), &$4);
+       }
+|      LBRA con ',' addr
+       {
+               outcode(int($1), &nullgen, int($2), &$4);
+       }
+|      LBRA con ',' '(' xlreg ')'
+       {
+               outcode(int($1), &nullgen, int($2), &$5);
+       }
+|      LBRA con ',' con ',' rel
+       {
+               var g obj.Addr
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int($4), &$6);
+       }
+|      LBRA con ',' con ',' addr
+       {
+               var g obj.Addr
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int($4), &$6);
+       }
+|      LBRA con ',' con ',' '(' xlreg ')'
+       {
+               var g obj.Addr
+               g = nullgen;
+               g.Type = D_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int($4), &$7);
+       }
+/*
+ * conditional trap
+ */
+|      LTRAP rreg ',' sreg
+       {
+               outcode(int($1), &$2, int($4), &nullgen);
+       }
+|      LTRAP imm ',' sreg
+       {
+               outcode(int($1), &$2, int($4), &nullgen);
+       }
+|      LTRAP rreg comma
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+|      LTRAP comma
+       {
+               outcode(int($1), &nullgen, NREG, &nullgen);
+       }
+/*
+ * floating point operate
+ */
+|      LFCONV freg ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFADD freg ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFADD freg ',' freg ',' freg
+       {
+               outcode(int($1), &$2, int($4.Reg), &$6);
+       }
+|      LFMA freg ',' freg ',' freg ',' freg
+       {
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+       }
+|      LFCMP freg ',' freg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LFCMP freg ',' freg ',' creg
+       {
+               outcode(int($1), &$2, int($6.Reg), &$4);
+       }
+/*
+ * CMP
+ */
+|      LCMP rreg ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LCMP rreg ',' imm
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LCMP rreg ',' rreg ',' creg
+       {
+               outcode(int($1), &$2, int($6.Reg), &$4);
+       }
+|      LCMP rreg ',' imm ',' creg
+       {
+               outcode(int($1), &$2, int($6.Reg), &$4);
+       }
+/*
+ * rotate and mask
+ */
+|      LRLWM  imm ',' rreg ',' imm ',' rreg
+       {
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+       }
+|      LRLWM  imm ',' rreg ',' mask ',' rreg
+       {
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+       }
+|      LRLWM  rreg ',' rreg ',' imm ',' rreg
+       {
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+       }
+|      LRLWM  rreg ',' rreg ',' mask ',' rreg
+       {
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+       }
+/*
+ * load/store multiple
+ */
+|      LMOVMW addr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LMOVMW rreg ',' addr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+/*
+ * various indexed load/store
+ * indexed unary (eg, cache clear)
+ */
+|      LXLD regaddr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LXLD regaddr ',' imm ',' rreg
+       {
+               outgcode(int($1), &$2, NREG, &$4, &$6);
+       }
+|      LXST rreg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LXST rreg ',' imm ',' regaddr
+       {
+               outgcode(int($1), &$2, NREG, &$4, &$6);
+       }
+|      LXMV regaddr ',' rreg
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LXMV rreg ',' regaddr
+       {
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LXOP regaddr
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+/*
+ * NOP
+ */
+|      LNOP comma
+       {
+               outcode(int($1), &nullgen, NREG, &nullgen);
+       }
+|      LNOP rreg comma
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+|      LNOP freg comma
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+|      LNOP ',' rreg
+       {
+               outcode(int($1), &nullgen, NREG, &$3);
+       }
+|      LNOP ',' freg
+       {
+               outcode(int($1), &nullgen, NREG, &$3);
+       }
+|      LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+/*
+ * word
+ */
+|      LWORD imm comma
+       {
+               outcode(int($1), &$2, NREG, &nullgen);
+       }
+|      LWORD ximm comma
+       {
+               outcode(int($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(int($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(int($1), &$2, NREG, &$4);
+       }
+/*
+ * END
+ */
+|      LEND comma
+       {
+               outcode(int($1), &nullgen, NREG, &nullgen);
+       }
+/*
+ * TEXT/GLOBL
+ */
+|      LTEXT name ',' imm
+       {
+               asm.Settext($2.Sym);
+               outcode(int($1), &$2, NREG, &$4);
+       }
+|      LTEXT name ',' con ',' imm
+       {
+               asm.Settext($2.Sym);
+               $6.Offset &= 0xffffffff;
+               $6.Offset |= -obj.ArgsSizeUnknown << 32;
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LTEXT name ',' con ',' imm '-' con
+       {
+               asm.Settext($2.Sym);
+               $6.Offset &= 0xffffffff;
+               $6.Offset |= ($8 & 0xffffffff) << 32;
+               outcode(int($1), &$2, int($4), &$6);
+       }
+/*
+ * DATA
+ */
+|      LDATA name '/' con ',' imm
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LDATA name '/' con ',' ximm
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+|      LDATA name '/' con ',' fimm
+       {
+               outcode(int($1), &$2, int($4), &$6);
+       }
+/*
+ * RETURN
+ */
+|      LRETRN  comma
+       {
+               outcode(int($1), &nullgen, NREG, &nullgen);
+       }
+
+rel:
+       con '(' LPC ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
+       }
+|      LNAME offset
+       {
+               $1 = asm.LabelLookup($1);
+               $$ = nullgen;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname)
+               }
+               $$.Type = D_BRANCH;
+               $$.Offset = $1.Value + $2;
+       }
+
+rreg:
+       sreg
+       {
+               $$ = nullgen;
+               $$.Type = D_REG;
+               $$.Reg = int8($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 = int16($1);
+               $$.Offset = $3;
+       }
+|      msr
+
+fpscr:
+       LFPSCR
+       {
+               $$ = nullgen;
+               $$.Type = D_FPSCR;
+               $$.Reg = NREG;
+       }
+
+fpscrf:
+       LFPSCR '(' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_FPSCR;
+               $$.Reg = int8($3);
+       }
+
+freg:
+       LFREG
+       {
+               $$ = nullgen;
+               $$.Type = D_FREG;
+               $$.Reg = int8($1);
+       }
+|      LF '(' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_FREG;
+               $$.Reg = int8($3);
+       }
+
+creg:
+       LCREG
+       {
+               $$ = nullgen;
+               $$.Type = D_CREG;
+               $$.Reg = int8($1);
+       }
+|      LCR '(' con ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_CREG;
+               $$.Reg = int8($3);
+       }
+
+
+cbit:  con
+       {
+               $$ = nullgen;
+               $$.Type = D_REG;
+               $$.Reg = int8($1);
+       }
+
+mask:
+       con ',' con
+       {
+               var mb, me int
+               var v uint32
+
+               $$ = nullgen;
+               $$.Type = D_CONST;
+               mb = int($1);
+               me = int($3);
+               if(mb < 0 || mb > 31 || me < 0 || me > 31){
+                       yyerror("illegal mask start/end value(s)");
+                       mb = 0
+                       me = 0;
+               }
+               if mb <= me {
+                       v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
+               } else {
+                       v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
+               }
+               $$.Offset = int64(v);
+       }
+
+ximm:
+       '$' addr
+       {
+               $$ = $2;
+               $$.Type = D_CONST;
+       }
+|      '$' LSCONST
+       {
+               $$ = nullgen;
+               $$.Type = D_SCONST;
+               $$.U.Sval = $2
+       }
+
+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 = int8($2);
+               $$.Offset = 0;
+       }
+|      '(' sreg '+' sreg ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Reg = int8($2);
+               $$.Scale = int8($4);
+               $$.Offset = 0;
+       }
+
+addr:
+       name
+|      con '(' sreg ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Reg = int8($3);
+               $$.Offset = $1;
+       }
+
+name:
+       con '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = int8($3);
+               $$.Sym = nil;
+               $$.Offset = $1;
+       }
+|      LNAME offset '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = int8($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
+       }
+|      LNAME '<' '>' offset '(' LSB ')'
+       {
+               $$ = nullgen;
+               $$.Type = D_OREG;
+               $$.Name = D_STATIC;
+               $$.Sym = obj.Linklookup(asm.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 << uint($4);
+       }
+|      expr '>' '>' expr
+       {
+               $$ = $1 >> uint($4);
+       }
+|      expr '&' expr
+       {
+               $$ = $1 & $3;
+       }
+|      expr '^' expr
+       {
+               $$ = $1 ^ $3;
+       }
+|      expr '|' expr
+       {
+               $$ = $1 | $3;
+       }
diff --git a/src/cmd/new9a/lex.go b/src/cmd/new9a/lex.go
new file mode 100644 (file)
index 0000000..c2c633e
--- /dev/null
@@ -0,0 +1,558 @@
+// cmd/9a/lex.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.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/ppc64"
+)
+
+var (
+       yyerror = asm.Yyerror
+       nullgen obj.Addr
+)
+
+func main() {
+       cinit()
+
+       asm.LSCONST = LSCONST
+       asm.LCONST = LCONST
+       asm.LFCONST = LFCONST
+       asm.LNAME = LNAME
+       asm.LVAR = LVAR
+       asm.LLAB = LLAB
+
+       asm.Lexinit = lexinit
+       asm.Cclean = cclean
+       asm.Yyparse = yyparse
+
+       asm.Thechar = '9'
+       asm.Thestring = "ppc64"
+       asm.Thelinkarch = &ppc64.Linkppc64
+       asm.Arches = map[string]*obj.LinkArch{
+               "ppc64le": &ppc64.Linkppc64le,
+       }
+
+       asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+       var av asm.Yylval
+       tok := asm.Yylex(&av)
+       v.sym = av.Sym
+       v.lval = av.Lval
+       v.sval = av.Sval
+       v.dval = av.Dval
+       return tok
+}
+
+func (yy) Error(msg string) {
+       asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+       nosched = 0
+       yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+       {"SP", LSP, ppc64.D_AUTO},
+       {"SB", LSB, ppc64.D_EXTERN},
+       {"FP", LFP, ppc64.D_PARAM},
+       {"PC", LPC, ppc64.D_BRANCH},
+       {"LR", LLR, ppc64.D_LR},
+       {"CTR", LCTR, ppc64.D_CTR},
+       {"XER", LSPREG, ppc64.D_XER},
+       {"MSR", LMSR, ppc64.D_MSR},
+       {"FPSCR", LFPSCR, ppc64.D_FPSCR},
+       {"SPR", LSPR, ppc64.D_SPR},
+       {"DCR", LSPR, ppc64.D_DCR},
+       {"CR", LCR, 0},
+       {"CR0", LCREG, 0},
+       {"CR1", LCREG, 1},
+       {"CR2", LCREG, 2},
+       {"CR3", LCREG, 3},
+       {"CR4", LCREG, 4},
+       {"CR5", LCREG, 5},
+       {"CR6", LCREG, 6},
+       {"CR7", LCREG, 7},
+       {"R", LR, 0},
+       {"R0", LREG, 0},
+       {"R1", LREG, 1},
+       {"R2", LREG, 2},
+       {"R3", LREG, 3},
+       {"R4", LREG, 4},
+       {"R5", LREG, 5},
+       {"R6", LREG, 6},
+       {"R7", LREG, 7},
+       {"R8", LREG, 8},
+       {"R9", LREG, 9},
+       {"R10", LREG, 10},
+       {"R11", LREG, 11},
+       {"R12", LREG, 12},
+       {"R13", LREG, 13},
+       {"R14", LREG, 14},
+       {"R15", LREG, 15},
+       {"R16", LREG, 16},
+       {"R17", LREG, 17},
+       {"R18", LREG, 18},
+       {"R19", LREG, 19},
+       {"R20", LREG, 20},
+       {"R21", LREG, 21},
+       {"R22", LREG, 22},
+       {"R23", LREG, 23},
+       {"R24", LREG, 24},
+       {"R25", LREG, 25},
+       {"R26", LREG, 26},
+       {"R27", LREG, 27},
+       {"R28", LREG, 28},
+       {"R29", LREG, 29},
+       {"g", LREG, 30}, // avoid unintentionally clobbering g using R30
+       {"R31", LREG, 31},
+       {"F", LF, 0},
+       {"F0", LFREG, 0},
+       {"F1", LFREG, 1},
+       {"F2", LFREG, 2},
+       {"F3", LFREG, 3},
+       {"F4", LFREG, 4},
+       {"F5", LFREG, 5},
+       {"F6", LFREG, 6},
+       {"F7", LFREG, 7},
+       {"F8", LFREG, 8},
+       {"F9", LFREG, 9},
+       {"F10", LFREG, 10},
+       {"F11", LFREG, 11},
+       {"F12", LFREG, 12},
+       {"F13", LFREG, 13},
+       {"F14", LFREG, 14},
+       {"F15", LFREG, 15},
+       {"F16", LFREG, 16},
+       {"F17", LFREG, 17},
+       {"F18", LFREG, 18},
+       {"F19", LFREG, 19},
+       {"F20", LFREG, 20},
+       {"F21", LFREG, 21},
+       {"F22", LFREG, 22},
+       {"F23", LFREG, 23},
+       {"F24", LFREG, 24},
+       {"F25", LFREG, 25},
+       {"F26", LFREG, 26},
+       {"F27", LFREG, 27},
+       {"F28", LFREG, 28},
+       {"F29", LFREG, 29},
+       {"F30", LFREG, 30},
+       {"F31", LFREG, 31},
+       {"CREQV", LCROP, ppc64.ACREQV},
+       {"CRXOR", LCROP, ppc64.ACRXOR},
+       {"CRAND", LCROP, ppc64.ACRAND},
+       {"CROR", LCROP, ppc64.ACROR},
+       {"CRANDN", LCROP, ppc64.ACRANDN},
+       {"CRORN", LCROP, ppc64.ACRORN},
+       {"CRNAND", LCROP, ppc64.ACRNAND},
+       {"CRNOR", LCROP, ppc64.ACRNOR},
+       {"ADD", LADDW, ppc64.AADD},
+       {"ADDV", LADDW, ppc64.AADDV},
+       {"ADDCC", LADDW, ppc64.AADDCC},
+       {"ADDVCC", LADDW, ppc64.AADDVCC},
+       {"ADDC", LADDW, ppc64.AADDC},
+       {"ADDCV", LADDW, ppc64.AADDCV},
+       {"ADDCCC", LADDW, ppc64.AADDCCC},
+       {"ADDCVCC", LADDW, ppc64.AADDCVCC},
+       {"ADDE", LLOGW, ppc64.AADDE},
+       {"ADDEV", LLOGW, ppc64.AADDEV},
+       {"ADDECC", LLOGW, ppc64.AADDECC},
+       {"ADDEVCC", LLOGW, ppc64.AADDEVCC},
+       {"ADDME", LABS, ppc64.AADDME},
+       {"ADDMEV", LABS, ppc64.AADDMEV},
+       {"ADDMECC", LABS, ppc64.AADDMECC},
+       {"ADDMEVCC", LABS, ppc64.AADDMEVCC},
+       {"ADDZE", LABS, ppc64.AADDZE},
+       {"ADDZEV", LABS, ppc64.AADDZEV},
+       {"ADDZECC", LABS, ppc64.AADDZECC},
+       {"ADDZEVCC", LABS, ppc64.AADDZEVCC},
+       {"SUB", LADDW, ppc64.ASUB},
+       {"SUBV", LADDW, ppc64.ASUBV},
+       {"SUBCC", LADDW, ppc64.ASUBCC},
+       {"SUBVCC", LADDW, ppc64.ASUBVCC},
+       {"SUBE", LLOGW, ppc64.ASUBE},
+       {"SUBECC", LLOGW, ppc64.ASUBECC},
+       {"SUBEV", LLOGW, ppc64.ASUBEV},
+       {"SUBEVCC", LLOGW, ppc64.ASUBEVCC},
+       {"SUBC", LADDW, ppc64.ASUBC},
+       {"SUBCCC", LADDW, ppc64.ASUBCCC},
+       {"SUBCV", LADDW, ppc64.ASUBCV},
+       {"SUBCVCC", LADDW, ppc64.ASUBCVCC},
+       {"SUBME", LABS, ppc64.ASUBME},
+       {"SUBMEV", LABS, ppc64.ASUBMEV},
+       {"SUBMECC", LABS, ppc64.ASUBMECC},
+       {"SUBMEVCC", LABS, ppc64.ASUBMEVCC},
+       {"SUBZE", LABS, ppc64.ASUBZE},
+       {"SUBZEV", LABS, ppc64.ASUBZEV},
+       {"SUBZECC", LABS, ppc64.ASUBZECC},
+       {"SUBZEVCC", LABS, ppc64.ASUBZEVCC},
+       {"AND", LADDW, ppc64.AAND},
+       {"ANDCC", LADDW, ppc64.AANDCC}, /* includes andil & andiu */
+       {"ANDN", LLOGW, ppc64.AANDN},
+       {"ANDNCC", LLOGW, ppc64.AANDNCC},
+       {"EQV", LLOGW, ppc64.AEQV},
+       {"EQVCC", LLOGW, ppc64.AEQVCC},
+       {"NAND", LLOGW, ppc64.ANAND},
+       {"NANDCC", LLOGW, ppc64.ANANDCC},
+       {"NOR", LLOGW, ppc64.ANOR},
+       {"NORCC", LLOGW, ppc64.ANORCC},
+       {"OR", LADDW, ppc64.AOR}, /* includes oril & oriu */
+       {"ORCC", LADDW, ppc64.AORCC},
+       {"ORN", LLOGW, ppc64.AORN},
+       {"ORNCC", LLOGW, ppc64.AORNCC},
+       {"XOR", LADDW, ppc64.AXOR}, /* includes xoril & xoriu */
+       {"XORCC", LLOGW, ppc64.AXORCC},
+       {"EXTSB", LABS, ppc64.AEXTSB},
+       {"EXTSBCC", LABS, ppc64.AEXTSBCC},
+       {"EXTSH", LABS, ppc64.AEXTSH},
+       {"EXTSHCC", LABS, ppc64.AEXTSHCC},
+       {"CNTLZW", LABS, ppc64.ACNTLZW},
+       {"CNTLZWCC", LABS, ppc64.ACNTLZWCC},
+       {"RLWMI", LRLWM, ppc64.ARLWMI},
+       {"RLWMICC", LRLWM, ppc64.ARLWMICC},
+       {"RLWNM", LRLWM, ppc64.ARLWNM},
+       {"RLWNMCC", LRLWM, ppc64.ARLWNMCC},
+       {"SLW", LSHW, ppc64.ASLW},
+       {"SLWCC", LSHW, ppc64.ASLWCC},
+       {"SRW", LSHW, ppc64.ASRW},
+       {"SRWCC", LSHW, ppc64.ASRWCC},
+       {"SRAW", LSHW, ppc64.ASRAW},
+       {"SRAWCC", LSHW, ppc64.ASRAWCC},
+       {"BR", LBRA, ppc64.ABR},
+       {"BC", LBRA, ppc64.ABC},
+       {"BCL", LBRA, ppc64.ABC},
+       {"BL", LBRA, ppc64.ABL},
+       {"BEQ", LBRA, ppc64.ABEQ},
+       {"BNE", LBRA, ppc64.ABNE},
+       {"BGT", LBRA, ppc64.ABGT},
+       {"BGE", LBRA, ppc64.ABGE},
+       {"BLT", LBRA, ppc64.ABLT},
+       {"BLE", LBRA, ppc64.ABLE},
+       {"BVC", LBRA, ppc64.ABVC},
+       {"BVS", LBRA, ppc64.ABVS},
+       {"CMP", LCMP, ppc64.ACMP},
+       {"CMPU", LCMP, ppc64.ACMPU},
+       {"CMPW", LCMP, ppc64.ACMPW},
+       {"CMPWU", LCMP, ppc64.ACMPWU},
+       {"DIVW", LLOGW, ppc64.ADIVW},
+       {"DIVWV", LLOGW, ppc64.ADIVWV},
+       {"DIVWCC", LLOGW, ppc64.ADIVWCC},
+       {"DIVWVCC", LLOGW, ppc64.ADIVWVCC},
+       {"DIVWU", LLOGW, ppc64.ADIVWU},
+       {"DIVWUV", LLOGW, ppc64.ADIVWUV},
+       {"DIVWUCC", LLOGW, ppc64.ADIVWUCC},
+       {"DIVWUVCC", LLOGW, ppc64.ADIVWUVCC},
+       {"FABS", LFCONV, ppc64.AFABS},
+       {"FABSCC", LFCONV, ppc64.AFABSCC},
+       {"FNEG", LFCONV, ppc64.AFNEG},
+       {"FNEGCC", LFCONV, ppc64.AFNEGCC},
+       {"FNABS", LFCONV, ppc64.AFNABS},
+       {"FNABSCC", LFCONV, ppc64.AFNABSCC},
+       {"FADD", LFADD, ppc64.AFADD},
+       {"FADDCC", LFADD, ppc64.AFADDCC},
+       {"FSUB", LFADD, ppc64.AFSUB},
+       {"FSUBCC", LFADD, ppc64.AFSUBCC},
+       {"FMUL", LFADD, ppc64.AFMUL},
+       {"FMULCC", LFADD, ppc64.AFMULCC},
+       {"FDIV", LFADD, ppc64.AFDIV},
+       {"FDIVCC", LFADD, ppc64.AFDIVCC},
+       {"FRSP", LFCONV, ppc64.AFRSP},
+       {"FRSPCC", LFCONV, ppc64.AFRSPCC},
+       {"FCTIW", LFCONV, ppc64.AFCTIW},
+       {"FCTIWCC", LFCONV, ppc64.AFCTIWCC},
+       {"FCTIWZ", LFCONV, ppc64.AFCTIWZ},
+       {"FCTIWZCC", LFCONV, ppc64.AFCTIWZCC},
+       {"FMADD", LFMA, ppc64.AFMADD},
+       {"FMADDCC", LFMA, ppc64.AFMADDCC},
+       {"FMSUB", LFMA, ppc64.AFMSUB},
+       {"FMSUBCC", LFMA, ppc64.AFMSUBCC},
+       {"FNMADD", LFMA, ppc64.AFNMADD},
+       {"FNMADDCC", LFMA, ppc64.AFNMADDCC},
+       {"FNMSUB", LFMA, ppc64.AFNMSUB},
+       {"FNMSUBCC", LFMA, ppc64.AFNMSUBCC},
+       {"FMADDS", LFMA, ppc64.AFMADDS},
+       {"FMADDSCC", LFMA, ppc64.AFMADDSCC},
+       {"FMSUBS", LFMA, ppc64.AFMSUBS},
+       {"FMSUBSCC", LFMA, ppc64.AFMSUBSCC},
+       {"FNMADDS", LFMA, ppc64.AFNMADDS},
+       {"FNMADDSCC", LFMA, ppc64.AFNMADDSCC},
+       {"FNMSUBS", LFMA, ppc64.AFNMSUBS},
+       {"FNMSUBSCC", LFMA, ppc64.AFNMSUBSCC},
+       {"FCMPU", LFCMP, ppc64.AFCMPU},
+       {"FCMPO", LFCMP, ppc64.AFCMPO},
+       {"MTFSB0", LMTFSB, ppc64.AMTFSB0},
+       {"MTFSB1", LMTFSB, ppc64.AMTFSB1},
+       {"FMOVD", LFMOV, ppc64.AFMOVD},
+       {"FMOVS", LFMOV, ppc64.AFMOVS},
+       {"FMOVDCC", LFCONV, ppc64.AFMOVDCC}, /* fmr. */
+       {"GLOBL", LTEXT, ppc64.AGLOBL},
+       {"MOVB", LMOVB, ppc64.AMOVB},
+       {"MOVBZ", LMOVB, ppc64.AMOVBZ},
+       {"MOVBU", LMOVB, ppc64.AMOVBU},
+       {"MOVBZU", LMOVB, ppc64.AMOVBZU},
+       {"MOVH", LMOVB, ppc64.AMOVH},
+       {"MOVHZ", LMOVB, ppc64.AMOVHZ},
+       {"MOVHU", LMOVB, ppc64.AMOVHU},
+       {"MOVHZU", LMOVB, ppc64.AMOVHZU},
+       {"MOVHBR", LXMV, ppc64.AMOVHBR},
+       {"MOVWBR", LXMV, ppc64.AMOVWBR},
+       {"MOVW", LMOVW, ppc64.AMOVW},
+       {"MOVWU", LMOVW, ppc64.AMOVWU},
+       {"MOVMW", LMOVMW, ppc64.AMOVMW},
+       {"MOVFL", LMOVW, ppc64.AMOVFL},
+       {"MULLW", LADDW, ppc64.AMULLW}, /* includes multiply immediate 10-139 */
+       {"MULLWV", LLOGW, ppc64.AMULLWV},
+       {"MULLWCC", LLOGW, ppc64.AMULLWCC},
+       {"MULLWVCC", LLOGW, ppc64.AMULLWVCC},
+       {"MULHW", LLOGW, ppc64.AMULHW},
+       {"MULHWCC", LLOGW, ppc64.AMULHWCC},
+       {"MULHWU", LLOGW, ppc64.AMULHWU},
+       {"MULHWUCC", LLOGW, ppc64.AMULHWUCC},
+       {"NEG", LABS, ppc64.ANEG},
+       {"NEGV", LABS, ppc64.ANEGV},
+       {"NEGCC", LABS, ppc64.ANEGCC},
+       {"NEGVCC", LABS, ppc64.ANEGVCC},
+       {"NOP", LNOP, ppc64.ANOP}, /* ori 0,0,0 */
+       {"SYSCALL", LNOP, ppc64.ASYSCALL},
+       {"UNDEF", LNOP, ppc64.AUNDEF},
+       {"RET", LRETRN, ppc64.ARETURN},
+       {"RETURN", LRETRN, ppc64.ARETURN},
+       {"RFI", LRETRN, ppc64.ARFI},
+       {"RFCI", LRETRN, ppc64.ARFCI},
+       {"DATA", LDATA, ppc64.ADATA},
+       {"END", LEND, ppc64.AEND},
+       {"TEXT", LTEXT, ppc64.ATEXT},
+
+       /* 64-bit instructions */
+       {"CNTLZD", LABS, ppc64.ACNTLZD},
+       {"CNTLZDCC", LABS, ppc64.ACNTLZDCC},
+       {"DIVD", LLOGW, ppc64.ADIVD},
+       {"DIVDCC", LLOGW, ppc64.ADIVDCC},
+       {"DIVDVCC", LLOGW, ppc64.ADIVDVCC},
+       {"DIVDV", LLOGW, ppc64.ADIVDV},
+       {"DIVDU", LLOGW, ppc64.ADIVDU},
+       {"DIVDUCC", LLOGW, ppc64.ADIVDUCC},
+       {"DIVDUVCC", LLOGW, ppc64.ADIVDUVCC},
+       {"DIVDUV", LLOGW, ppc64.ADIVDUV},
+       {"EXTSW", LABS, ppc64.AEXTSW},
+       {"EXTSWCC", LABS, ppc64.AEXTSWCC},
+       {"FCTID", LFCONV, ppc64.AFCTID},
+       {"FCTIDCC", LFCONV, ppc64.AFCTIDCC},
+       {"FCTIDZ", LFCONV, ppc64.AFCTIDZ},
+       {"FCTIDZCC", LFCONV, ppc64.AFCTIDZCC},
+       {"FCFID", LFCONV, ppc64.AFCFID},
+       {"FCFIDCC", LFCONV, ppc64.AFCFIDCC},
+       {"LDAR", LXLD, ppc64.ALDAR},
+       {"MOVD", LMOVW, ppc64.AMOVD},
+       {"MOVDU", LMOVW, ppc64.AMOVDU},
+       {"MOVWZ", LMOVW, ppc64.AMOVWZ},
+       {"MOVWZU", LMOVW, ppc64.AMOVWZU},
+       {"MULHD", LLOGW, ppc64.AMULHD},
+       {"MULHDCC", LLOGW, ppc64.AMULHDCC},
+       {"MULHDU", LLOGW, ppc64.AMULHDU},
+       {"MULHDUCC", LLOGW, ppc64.AMULHDUCC},
+       {"MULLD", LADDW, ppc64.AMULLD}, /* includes multiply immediate? */
+       {"MULLDCC", LLOGW, ppc64.AMULLDCC},
+       {"MULLDVCC", LLOGW, ppc64.AMULLDVCC},
+       {"MULLDV", LLOGW, ppc64.AMULLDV},
+       {"RFID", LRETRN, ppc64.ARFID},
+       {"HRFID", LRETRN, ppc64.AHRFID},
+       {"RLDMI", LRLWM, ppc64.ARLDMI},
+       {"RLDMICC", LRLWM, ppc64.ARLDMICC},
+       {"RLDC", LRLWM, ppc64.ARLDC},
+       {"RLDCCC", LRLWM, ppc64.ARLDCCC},
+       {"RLDCR", LRLWM, ppc64.ARLDCR},
+       {"RLDCRCC", LRLWM, ppc64.ARLDCRCC},
+       {"RLDCL", LRLWM, ppc64.ARLDCL},
+       {"RLDCLCC", LRLWM, ppc64.ARLDCLCC},
+       {"SLBIA", LNOP, ppc64.ASLBIA},
+       {"SLBIE", LNOP, ppc64.ASLBIE},
+       {"SLBMFEE", LABS, ppc64.ASLBMFEE},
+       {"SLBMFEV", LABS, ppc64.ASLBMFEV},
+       {"SLBMTE", LABS, ppc64.ASLBMTE},
+       {"SLD", LSHW, ppc64.ASLD},
+       {"SLDCC", LSHW, ppc64.ASLDCC},
+       {"SRD", LSHW, ppc64.ASRD},
+       {"SRAD", LSHW, ppc64.ASRAD},
+       {"SRADCC", LSHW, ppc64.ASRADCC},
+       {"SRDCC", LSHW, ppc64.ASRDCC},
+       {"STDCCC", LXST, ppc64.ASTDCCC},
+       {"TD", LADDW, ppc64.ATD},
+
+       /* pseudo instructions */
+       {"REM", LLOGW, ppc64.AREM},
+       {"REMCC", LLOGW, ppc64.AREMCC},
+       {"REMV", LLOGW, ppc64.AREMV},
+       {"REMVCC", LLOGW, ppc64.AREMVCC},
+       {"REMU", LLOGW, ppc64.AREMU},
+       {"REMUCC", LLOGW, ppc64.AREMUCC},
+       {"REMUV", LLOGW, ppc64.AREMUV},
+       {"REMUVCC", LLOGW, ppc64.AREMUVCC},
+       {"REMD", LLOGW, ppc64.AREMD},
+       {"REMDCC", LLOGW, ppc64.AREMDCC},
+       {"REMDV", LLOGW, ppc64.AREMDV},
+       {"REMDVCC", LLOGW, ppc64.AREMDVCC},
+       {"REMDU", LLOGW, ppc64.AREMDU},
+       {"REMDUCC", LLOGW, ppc64.AREMDUCC},
+       {"REMDUV", LLOGW, ppc64.AREMDUV},
+       {"REMDUVCC", LLOGW, ppc64.AREMDUVCC},
+
+       /* special instructions */
+       {"DCBF", LXOP, ppc64.ADCBF},
+       {"DCBI", LXOP, ppc64.ADCBI},
+       {"DCBST", LXOP, ppc64.ADCBST},
+       {"DCBT", LXOP, ppc64.ADCBT},
+       {"DCBTST", LXOP, ppc64.ADCBTST},
+       {"DCBZ", LXOP, ppc64.ADCBZ},
+       {"ICBI", LXOP, ppc64.AICBI},
+       {"ECIWX", LXLD, ppc64.AECIWX},
+       {"ECOWX", LXST, ppc64.AECOWX},
+       {"LWAR", LXLD, ppc64.ALWAR},
+       {"STWCCC", LXST, ppc64.ASTWCCC},
+       {"EIEIO", LRETRN, ppc64.AEIEIO},
+       {"TLBIE", LNOP, ppc64.ATLBIE},
+       {"TLBIEL", LNOP, ppc64.ATLBIEL},
+       {"LSW", LXLD, ppc64.ALSW},
+       {"STSW", LXST, ppc64.ASTSW},
+       {"ISYNC", LRETRN, ppc64.AISYNC},
+       {"SYNC", LRETRN, ppc64.ASYNC},
+       {"TLBSYNC", LRETRN, ppc64.ATLBSYNC},
+       {"PTESYNC", LRETRN, ppc64.APTESYNC},
+
+       /*      "TW",           LADDW,  ATW,*/
+       {"WORD", LWORD, ppc64.AWORD},
+       {"DWORD", LWORD, ppc64.ADWORD},
+       {"SCHED", LSCHED, 0},
+       {"NOSCHED", LSCHED, 0x80},
+       {"PCDATA", LPCDAT, ppc64.APCDATA},
+       {"FUNCDATA", LFUNCDAT, ppc64.AFUNCDATA},
+}
+
+func cinit() {
+       nullgen.Type = ppc64.D_NONE
+       nullgen.Name = ppc64.D_NONE
+       nullgen.Reg = ppc64.NREG
+       nullgen.Scale = ppc64.NREG // replaced Gen.xreg with Prog.scale
+}
+
+func cclean() {
+       outcode(ppc64.AEND, &nullgen, ppc64.NREG, &nullgen)
+}
+
+var lastpc *obj.Prog
+var nosched int
+
+func outcode(a int, g1 *obj.Addr, reg int, g2 *obj.Addr) {
+       var p *obj.Prog
+       var pl *obj.Plist
+
+       if asm.Pass == 1 {
+               goto out
+       }
+
+       if g1.Scale != ppc64.NREG {
+               if reg != ppc64.NREG || g2.Scale != ppc64.NREG {
+                       yyerror("bad addressing modes")
+               }
+               reg = int(g1.Scale)
+       } else if g2.Scale != ppc64.NREG {
+               if reg != ppc64.NREG {
+                       yyerror("bad addressing modes")
+               }
+               reg = int(g2.Scale)
+       }
+
+       p = asm.Ctxt.NewProg()
+       p.As = int16(a)
+       p.Lineno = asm.Lineno
+       if nosched != 0 {
+               p.Mark |= ppc64.NOSCHED
+       }
+       p.From = *g1
+       p.Reg = uint8(reg)
+       p.To = *g2
+       p.Pc = int64(asm.PC)
+
+       if lastpc == nil {
+               pl = obj.Linknewplist(asm.Ctxt)
+               pl.Firstpc = p
+       } else {
+               lastpc.Link = p
+       }
+       lastpc = p
+
+out:
+       if a != ppc64.AGLOBL && a != ppc64.ADATA {
+               asm.PC++
+       }
+}
+
+func outgcode(a int, g1 *obj.Addr, reg int, g2, g3 *obj.Addr) {
+       var p *obj.Prog
+       var pl *obj.Plist
+
+       if asm.Pass == 1 {
+               goto out
+       }
+
+       p = asm.Ctxt.NewProg()
+       p.As = int16(a)
+       p.Lineno = asm.Lineno
+       if nosched != 0 {
+               p.Mark |= ppc64.NOSCHED
+       }
+       p.From = *g1
+       p.Reg = uint8(reg)
+       p.From3 = *g2
+       p.To = *g3
+       p.Pc = int64(asm.PC)
+
+       if lastpc == nil {
+               pl = obj.Linknewplist(asm.Ctxt)
+               pl.Firstpc = p
+       } else {
+               lastpc.Link = p
+       }
+       lastpc = p
+
+out:
+       if a != ppc64.AGLOBL && a != ppc64.ADATA {
+               asm.PC++
+       }
+}
diff --git a/src/cmd/new9a/y.go b/src/cmd/new9a/y.go
new file mode 100644 (file)
index 0000000..43aa429
--- /dev/null
@@ -0,0 +1,1694 @@
+//line a.y:31
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:31
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/ppc64"
+)
+
+//line a.y:40
+type yySymType struct {
+       yys  int
+       sym  *asm.Sym
+       lval int64
+       dval float64
+       sval string
+       addr obj.Addr
+}
+
+const LMOVW = 57346
+const LMOVB = 57347
+const LABS = 57348
+const LLOGW = 57349
+const LSHW = 57350
+const LADDW = 57351
+const LCMP = 57352
+const LCROP = 57353
+const LBRA = 57354
+const LFMOV = 57355
+const LFCONV = 57356
+const LFCMP = 57357
+const LFADD = 57358
+const LFMA = 57359
+const LTRAP = 57360
+const LXORW = 57361
+const LNOP = 57362
+const LEND = 57363
+const LRETT = 57364
+const LWORD = 57365
+const LTEXT = 57366
+const LDATA = 57367
+const LRETRN = 57368
+const LCONST = 57369
+const LSP = 57370
+const LSB = 57371
+const LFP = 57372
+const LPC = 57373
+const LCREG = 57374
+const LFLUSH = 57375
+const LREG = 57376
+const LFREG = 57377
+const LR = 57378
+const LCR = 57379
+const LF = 57380
+const LFPSCR = 57381
+const LLR = 57382
+const LCTR = 57383
+const LSPR = 57384
+const LSPREG = 57385
+const LSEG = 57386
+const LMSR = 57387
+const LPCDAT = 57388
+const LFUNCDAT = 57389
+const LSCHED = 57390
+const LXLD = 57391
+const LXST = 57392
+const LXOP = 57393
+const LXMV = 57394
+const LRLWM = 57395
+const LMOVMW = 57396
+const LMOVEM = 57397
+const LMOVFL = 57398
+const LMTFSB = 57399
+const LMA = 57400
+const LFCONST = 57401
+const LSCONST = 57402
+const LNAME = 57403
+const LLAB = 57404
+const LVAR = 57405
+
+var yyToknames = []string{
+       "'|'",
+       "'^'",
+       "'&'",
+       "'<'",
+       "'>'",
+       "'+'",
+       "'-'",
+       "'*'",
+       "'/'",
+       "'%'",
+       "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",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+       -1, 1,
+       1, -1,
+       -2, 0,
+}
+
+const yyNprod = 183
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 885
+
+var yyAct = []int{
+
+       46, 52, 88, 421, 100, 431, 103, 169, 2, 92,
+       64, 83, 56, 276, 93, 95, 96, 98, 99, 50,
+       54, 111, 49, 271, 55, 444, 119, 121, 123, 443,
+       126, 128, 432, 131, 89, 136, 72, 411, 73, 78,
+       77, 125, 125, 92, 115, 116, 117, 118, 410, 72,
+       61, 73, 72, 62, 73, 132, 400, 51, 161, 399,
+       78, 442, 381, 380, 202, 440, 377, 75, 366, 53,
+       91, 94, 92, 97, 365, 364, 78, 77, 112, 363,
+       81, 82, 133, 275, 120, 92, 125, 146, 75, 107,
+       134, 135, 137, 138, 72, 361, 73, 59, 59, 59,
+       145, 147, 360, 76, 75, 314, 101, 108, 102, 65,
+       401, 79, 359, 196, 110, 59, 282, 203, 195, 202,
+       183, 164, 74, 159, 76, 141, 141, 114, 45, 102,
+       92, 48, 79, 229, 222, 201, 202, 166, 109, 168,
+       76, 167, 85, 87, 106, 105, 162, 439, 79, 244,
+       252, 253, 165, 231, 261, 263, 223, 267, 268, 269,
+       124, 250, 127, 129, 438, 173, 174, 175, 437, 251,
+       436, 256, 435, 249, 392, 258, 265, 286, 289, 290,
+       186, 391, 390, 389, 388, 387, 386, 385, 301, 303,
+       305, 307, 309, 310, 199, 384, 383, 382, 376, 312,
+       375, 374, 291, 292, 293, 294, 247, 316, 319, 257,
+       373, 315, 330, 332, 333, 334, 372, 336, 248, 340,
+       371, 370, 259, 369, 358, 264, 266, 357, 228, 227,
+       326, 327, 328, 329, 226, 114, 59, 219, 218, 59,
+       217, 216, 215, 214, 213, 300, 212, 211, 210, 209,
+       278, 163, 208, 207, 279, 280, 281, 206, 204, 284,
+       285, 47, 84, 86, 59, 200, 194, 193, 192, 331,
+       59, 104, 191, 298, 337, 339, 78, 77, 190, 122,
+       246, 189, 313, 255, 342, 188, 344, 113, 199, 322,
+       187, 368, 347, 348, 349, 350, 351, 185, 182, 354,
+       355, 356, 181, 59, 75, 57, 367, 180, 288, 179,
+       178, 72, 177, 73, 296, 59, 345, 176, 346, 158,
+       130, 157, 156, 155, 139, 154, 153, 143, 152, 78,
+       77, 378, 151, 150, 379, 149, 148, 44, 74, 43,
+       76, 42, 40, 41, 297, 60, 63, 396, 79, 338,
+       72, 341, 73, 61, 184, 262, 62, 75, 197, 65,
+       433, 78, 77, 230, 110, 61, 160, 72, 62, 73,
+       402, 403, 404, 405, 406, 407, 408, 441, 397, 353,
+       65, 409, 395, 61, 283, 110, 62, 412, 352, 75,
+       425, 74, 424, 76, 429, 430, 171, 172, 60, 205,
+       245, 79, 7, 254, 144, 415, 416, 1, 78, 77,
+       69, 393, 394, 183, 72, 61, 73, 260, 62, 220,
+       221, 297, 71, 224, 225, 76, 70, 434, 287, 0,
+       102, 160, 0, 79, 295, 58, 75, 446, 447, 0,
+       449, 450, 78, 77, 0, 420, 423, 398, 0, 427,
+       428, 0, 317, 320, 417, 418, 419, 65, 445, 72,
+       0, 73, 110, 0, 101, 270, 0, 335, 199, 0,
+       75, 0, 76, 140, 142, 422, 422, 102, 61, 343,
+       79, 62, 0, 242, 241, 240, 238, 239, 233, 234,
+       235, 236, 237, 299, 302, 304, 306, 308, 0, 311,
+       0, 273, 272, 274, 74, 0, 76, 72, 270, 73,
+       324, 60, 325, 90, 79, 273, 272, 274, 170, 165,
+       171, 172, 426, 65, 0, 0, 448, 0, 110, 451,
+       173, 8, 0, 68, 67, 0, 80, 233, 234, 235,
+       236, 237, 0, 9, 10, 16, 14, 15, 13, 25,
+       18, 19, 11, 21, 24, 22, 23, 20, 277, 32,
+       36, 0, 33, 37, 38, 39, 0, 78, 77, 0,
+       0, 78, 77, 273, 272, 274, 323, 0, 0, 72,
+       0, 73, 362, 0, 0, 34, 35, 5, 28, 29,
+       31, 30, 26, 27, 0, 75, 12, 17, 0, 75,
+       3, 0, 4, 0, 65, 6, 72, 61, 73, 66,
+       62, 63, 81, 82, 68, 67, 0, 80, 78, 77,
+       241, 240, 238, 239, 233, 234, 235, 236, 237, 78,
+       77, 76, 413, 74, 0, 76, 102, 0, 92, 79,
+       60, 0, 64, 79, 78, 77, 75, 0, 78, 77,
+       0, 65, 0, 72, 0, 73, 66, 75, 0, 81,
+       82, 68, 67, 0, 80, 0, 0, 78, 77, 63,
+       0, 0, 75, 235, 236, 237, 75, 0, 0, 72,
+       74, 73, 76, 78, 77, 0, 0, 60, 0, 92,
+       79, 74, 0, 76, 0, 75, 78, 77, 60, 0,
+       92, 79, 72, 0, 73, 0, 74, 0, 76, 164,
+       74, 75, 76, 102, 78, 77, 79, 102, 78, 77,
+       79, 0, 0, 0, 75, 0, 0, 0, 0, 78,
+       77, 76, 0, 0, 0, 0, 102, 0, 0, 79,
+       0, 0, 75, 0, 0, 109, 75, 76, 0, 0,
+       0, 0, 414, 0, 0, 79, 0, 75, 74, 0,
+       76, 0, 0, 0, 0, 102, 0, 0, 79, 238,
+       239, 233, 234, 235, 236, 237, 109, 0, 76, 0,
+       109, 0, 76, 321, 0, 0, 79, 318, 0, 0,
+       79, 109, 0, 76, 0, 0, 0, 0, 198, 0,
+       0, 79, 242, 241, 240, 238, 239, 233, 234, 235,
+       236, 237, 242, 241, 240, 238, 239, 233, 234, 235,
+       236, 237, 240, 238, 239, 233, 234, 235, 236, 237,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 243, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 232,
+}
+var yyPact = []int{
+
+       -1000, 529, -1000, 268, 266, 263, -1000, 261, 52, 562,
+       267, 433, -71, -8, 323, -8, 323, 323, 399, 67,
+       50, 308, 308, 308, 308, 323, -8, 635, -36, 323,
+       8, -36, 5, -70, -71, -71, 158, 687, 687, 158,
+       -1000, 399, 399, -1000, -1000, -1000, 259, 258, 256, 255,
+       251, 249, 248, 246, 245, 244, 242, -1000, -1000, 45,
+       658, -1000, 68, -1000, 639, -1000, 59, -1000, 63, -1000,
+       -1000, -1000, -1000, 61, 511, -1000, -1000, 399, 399, 399,
+       -1000, -1000, -1000, 240, 235, 233, 232, 230, 225, 221,
+       344, 220, 399, 213, 208, 204, 201, 195, 191, 190,
+       189, -1000, 399, -1000, -1000, 30, 720, 188, 58, 511,
+       59, 181, 180, -1000, -1000, 176, 175, 172, 171, 170,
+       169, 167, 166, 165, 164, 323, 163, 161, 160, -1000,
+       -1000, 158, 158, 370, -1000, 158, 158, 157, 152, -1000,
+       151, 55, 351, -1000, 529, 808, -1000, 798, 609, 323,
+       323, 620, 338, 306, 323, 481, 415, 323, 323, 463,
+       4, 479, 399, -1000, -1000, 45, 399, 399, 399, 38,
+       376, 399, 399, -1000, -1000, -1000, 267, 323, 323, 308,
+       308, 308, 320, -1000, 275, 399, -1000, -8, 323, 323,
+       323, 323, 323, 323, 399, 26, -1000, -1000, 30, 41,
+       709, 705, 535, 38, 323, -1000, 323, 308, 308, 308,
+       308, -8, 323, 323, 323, 687, -8, -37, 323, -36,
+       -1000, -1000, -1000, -1000, -1000, -1000, -71, 687, 558, 477,
+       399, -1000, -1000, 399, 399, 399, 399, 399, 381, 371,
+       399, 399, 399, -1000, -1000, -1000, -1000, 150, -1000, -1000,
+       -1000, -1000, -1000, -1000, -1000, -1000, -1000, 147, -1000, -1000,
+       -1000, -1000, 34, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+       23, 16, -1000, -1000, -1000, -1000, 323, -1000, 0, -4,
+       -5, -11, 477, 387, -1000, -1000, -1000, -1000, -1000, -1000,
+       -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 146,
+       144, -1000, 143, -1000, 139, -1000, 133, -1000, 124, -1000,
+       -1000, 123, -1000, 121, -1000, -13, -1000, -1000, 30, -1000,
+       -1000, 30, -14, -17, -1000, -1000, -1000, 120, 119, 118,
+       110, 109, 108, 107, -1000, -1000, -1000, 106, -1000, 105,
+       -1000, -1000, -1000, -1000, -1000, 104, 97, 662, 662, -1000,
+       -1000, -1000, 399, 399, 762, 816, 615, 300, 297, 399,
+       -1000, -1000, -20, -1000, -1000, -1000, -1000, -23, 32, 323,
+       323, 323, 323, 323, 323, 323, 399, -1000, -31, -42,
+       674, -1000, 308, 308, 317, 317, 317, 558, 558, 323,
+       -36, -71, -75, 528, 528, -1000, -1000, -1000, -47, -1000,
+       -1000, 321, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+       -1000, -1000, -1000, -1000, 30, -1000, 95, -1000, -1000, -1000,
+       93, 91, 87, 70, -12, -1000, -1000, 367, -1000, -1000,
+       -1000, 51, -1000, -50, -54, 308, 323, 323, 399, 323,
+       323, 399, 352, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+       -1000, -1000,
+}
+var yyPgo = []int{
+
+       0, 87, 58, 23, 7, 305, 251, 0, 131, 435,
+       69, 22, 12, 426, 422, 57, 1, 2, 6, 20,
+       24, 4, 19, 417, 410, 3, 407, 8, 404, 402,
+       287,
+}
+var yyR1 = []int{
+
+       0, 26, 26, 28, 27, 27, 27, 27, 27, 27,
+       27, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+       29, 29, 29, 29, 18, 18, 7, 12, 12, 13,
+       20, 14, 24, 19, 19, 19, 22, 23, 11, 11,
+       10, 10, 21, 25, 16, 16, 17, 17, 15, 5,
+       5, 8, 8, 6, 6, 9, 9, 9, 30, 30,
+       4, 4, 4, 3, 3, 3, 1, 1, 1, 1,
+       1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+       2, 2, 2,
+}
+var yyR2 = []int{
+
+       0, 0, 2, 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, 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,
+}
+var yyChk = []int{
+
+       -1000, -26, -27, 71, 73, 58, 76, -29, 2, 14,
+       15, 23, 67, 19, 17, 18, 16, 68, 21, 22,
+       28, 24, 26, 27, 25, 20, 63, 64, 59, 60,
+       62, 61, 30, 33, 56, 57, 31, 34, 35, 36,
+       74, 75, 75, 76, 76, 76, -7, -6, -8, -11,
+       -22, -15, -16, -10, -19, -20, -12, -5, -9, -1,
+       78, 45, 48, 49, 80, 42, 47, 53, 52, -24,
+       -13, -14, 44, 46, 71, 37, 73, 10, 9, 81,
+       55, 50, 51, -7, -6, -8, -6, -8, -17, -11,
+       80, -15, 80, -7, -15, -7, -7, -15, -7, -7,
+       -21, -1, 78, -18, -6, 78, 77, -10, -1, 71,
+       47, -7, -15, -30, 77, -11, -11, -11, -11, -7,
+       -15, -7, -6, -7, -8, 78, -7, -8, -7, -8,
+       -30, -7, -11, 77, -15, -15, -16, -15, -15, -30,
+       -9, -1, -9, -30, -28, -2, -1, -2, 77, 77,
+       77, 77, 77, 77, 77, 77, 77, 77, 77, 78,
+       -5, -2, 78, -6, 70, -1, 78, 78, 78, -4,
+       7, 9, 10, -1, -1, -1, 77, 77, 77, 77,
+       77, 77, 77, 69, 10, 77, -1, 77, 77, 77,
+       77, 77, 77, 77, 77, -12, -18, -6, 78, -1,
+       77, 77, 78, -4, 77, -30, 77, 77, 77, 77,
+       77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+       -30, -30, -7, -11, -30, -30, 77, 77, 77, 78,
+       12, -27, 76, 9, 10, 11, 12, 13, 7, 8,
+       6, 5, 4, 76, -7, -6, -8, -15, -10, -20,
+       -12, -19, -7, -7, -6, -8, -22, -15, -11, -10,
+       -23, -7, 49, -7, -10, -19, -10, -7, -7, -7,
+       -5, -3, 39, 38, 40, 79, 9, 79, -1, -1,
+       -1, -1, 78, 8, -1, -1, -7, -6, -8, -7,
+       -7, -11, -11, -11, -11, -6, -8, 69, -1, -5,
+       -15, -7, -5, -7, -5, -7, -5, -7, -5, -7,
+       -7, -5, -21, -1, 79, -12, -18, -6, 78, -18,
+       -6, 78, -1, 41, -5, -5, -11, -11, -11, -11,
+       -7, -15, -7, -7, -7, -6, -7, -15, -8, -15,
+       -7, -8, -15, -6, -15, -1, -1, -2, -2, -2,
+       -2, -2, 7, 8, -2, -2, -2, 77, 77, 78,
+       79, 79, -5, 79, 79, 79, 79, -3, -4, 77,
+       77, 77, 77, 77, 77, 77, 77, 79, -12, -12,
+       77, 79, 77, 77, 77, 77, 77, 77, 77, 77,
+       77, 77, 77, -2, -2, -20, 47, -22, -1, 79,
+       79, 78, -7, -7, -7, -7, -7, -7, -7, -21,
+       79, 79, -18, -6, 78, -11, -11, -10, -10, -10,
+       -15, -25, -1, -15, -25, -7, -8, -15, -15, -16,
+       -17, 80, 79, 39, -12, 77, 77, 77, 77, 77,
+       77, 10, 10, 79, 79, -11, -7, -7, -1, -7,
+       -7, -1,
+}
+var yyDef = []int{
+
+       1, -2, 2, 0, 0, 0, 8, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       158, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 158, 0, 0, 0, 158, 0, 0, 158,
+       3, 0, 0, 7, 9, 10, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 126, 153, 0,
+       0, 138, 0, 136, 0, 140, 130, 133, 0, 135,
+       127, 128, 149, 0, 160, 166, 167, 0, 0, 0,
+       132, 129, 131, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 50, 0,
+       0, 142, 0, 64, 65, 0, 0, 0, 0, 160,
+       0, 158, 0, 82, 159, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 105,
+       106, 158, 158, 159, 111, 158, 158, 0, 0, 116,
+       0, 0, 0, 123, 0, 0, 172, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 144, 145, 148, 0, 0, 0, 0,
+       0, 0, 0, 168, 169, 170, 0, 0, 0, 0,
+       0, 0, 0, 146, 0, 0, 148, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 67, 68, 0, 0,
+       0, 0, 0, 125, 159, 81, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       107, 108, 109, 110, 112, 113, 0, 0, 0, 0,
+       0, 4, 5, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 6, 11, 23, 24, 0, 36, 37,
+       61, 63, 12, 13, 27, 28, 30, 0, 29, 32,
+       33, 52, 0, 53, 56, 62, 57, 59, 58, 60,
+       0, 0, 163, 164, 165, 151, 0, 171, 0, 0,
+       0, 0, 0, 160, 161, 162, 14, 25, 26, 15,
+       16, 17, 18, 19, 20, 21, 22, 147, 34, 126,
+       0, 41, 126, 42, 126, 44, 126, 46, 126, 48,
+       49, 0, 54, 142, 66, 0, 70, 71, 0, 73,
+       74, 0, 0, 0, 79, 80, 83, 84, 0, 87,
+       89, 90, 0, 0, 97, 98, 99, 0, 101, 0,
+       103, 104, 114, 115, 117, 0, 0, 173, 174, 175,
+       176, 177, 0, 0, 180, 181, 182, 0, 0, 0,
+       154, 155, 0, 139, 141, 134, 150, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 69, 0, 0,
+       0, 124, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 178, 179, 35, 130, 31, 0, 152,
+       156, 0, 38, 40, 39, 43, 45, 47, 51, 55,
+       72, 75, 76, 77, 0, 85, 0, 88, 91, 92,
+       0, 0, 0, 0, 0, 100, 102, 118, 120, 121,
+       122, 0, 137, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 157, 78, 86, 93, 94, 143, 95,
+       96, 119,
+}
+var yyTok1 = []int{
+
+       1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 80, 13, 6, 3,
+       78, 79, 11, 9, 77, 10, 3, 12, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 74, 76,
+       7, 75, 8, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       3, 3, 3, 3, 4, 3, 81,
+}
+var yyTok2 = []int{
+
+       2, 3, 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, 73,
+}
+var yyTok3 = []int{
+       0,
+}
+
+//line yaccpar:1
+
+/*     parser for yacc output  */
+
+var yyDebug = 0
+
+type yyLexer interface {
+       Lex(lval *yySymType) int
+       Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+       // 4 is TOKSTART above
+       if c >= 4 && c-4 < len(yyToknames) {
+               if yyToknames[c-4] != "" {
+                       return yyToknames[c-4]
+               }
+       }
+       return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+       if s >= 0 && s < len(yyStatenames) {
+               if yyStatenames[s] != "" {
+                       return yyStatenames[s]
+               }
+       }
+       return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+       c := 0
+       char := lex.Lex(lval)
+       if char <= 0 {
+               c = yyTok1[0]
+               goto out
+       }
+       if char < len(yyTok1) {
+               c = yyTok1[char]
+               goto out
+       }
+       if char >= yyPrivate {
+               if char < yyPrivate+len(yyTok2) {
+                       c = yyTok2[char-yyPrivate]
+                       goto out
+               }
+       }
+       for i := 0; i < len(yyTok3); i += 2 {
+               c = yyTok3[i+0]
+               if c == char {
+                       c = yyTok3[i+1]
+                       goto out
+               }
+       }
+
+out:
+       if c == 0 {
+               c = yyTok2[1] /* unknown char */
+       }
+       if yyDebug >= 3 {
+               __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+       }
+       return c
+}
+
+func yyParse(yylex yyLexer) int {
+       var yyn int
+       var yylval yySymType
+       var yyVAL yySymType
+       yyS := make([]yySymType, yyMaxDepth)
+
+       Nerrs := 0   /* number of errors */
+       Errflag := 0 /* error recovery flag */
+       yystate := 0
+       yychar := -1
+       yyp := -1
+       goto yystack
+
+ret0:
+       return 0
+
+ret1:
+       return 1
+
+yystack:
+       /* put a state and value onto the stack */
+       if yyDebug >= 4 {
+               __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+       }
+
+       yyp++
+       if yyp >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyS[yyp] = yyVAL
+       yyS[yyp].yys = yystate
+
+yynewstate:
+       yyn = yyPact[yystate]
+       if yyn <= yyFlag {
+               goto yydefault /* simple state */
+       }
+       if yychar < 0 {
+               yychar = yylex1(yylex, &yylval)
+       }
+       yyn += yychar
+       if yyn < 0 || yyn >= yyLast {
+               goto yydefault
+       }
+       yyn = yyAct[yyn]
+       if yyChk[yyn] == yychar { /* valid shift */
+               yychar = -1
+               yyVAL = yylval
+               yystate = yyn
+               if Errflag > 0 {
+                       Errflag--
+               }
+               goto yystack
+       }
+
+yydefault:
+       /* default state action */
+       yyn = yyDef[yystate]
+       if yyn == -2 {
+               if yychar < 0 {
+                       yychar = yylex1(yylex, &yylval)
+               }
+
+               /* look through exception table */
+               xi := 0
+               for {
+                       if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+                               break
+                       }
+                       xi += 2
+               }
+               for xi += 2; ; xi += 2 {
+                       yyn = yyExca[xi+0]
+                       if yyn < 0 || yyn == yychar {
+                               break
+                       }
+               }
+               yyn = yyExca[xi+1]
+               if yyn < 0 {
+                       goto ret0
+               }
+       }
+       if yyn == 0 {
+               /* error ... attempt to resume parsing */
+               switch Errflag {
+               case 0: /* brand new error */
+                       yylex.Error("syntax error")
+                       Nerrs++
+                       if yyDebug >= 1 {
+                               __yyfmt__.Printf("%s", yyStatname(yystate))
+                               __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+                       }
+                       fallthrough
+
+               case 1, 2: /* incompletely recovered error ... try again */
+                       Errflag = 3
+
+                       /* find a state where "error" is a legal shift action */
+                       for yyp >= 0 {
+                               yyn = yyPact[yyS[yyp].yys] + yyErrCode
+                               if yyn >= 0 && yyn < yyLast {
+                                       yystate = yyAct[yyn] /* simulate a shift of "error" */
+                                       if yyChk[yystate] == yyErrCode {
+                                               goto yystack
+                                       }
+                               }
+
+                               /* the current p has no shift on "error", pop stack */
+                               if yyDebug >= 2 {
+                                       __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+                               }
+                               yyp--
+                       }
+                       /* there is no state on the stack with an error shift ... abort */
+                       goto ret1
+
+               case 3: /* no shift yet; clobber input char */
+                       if yyDebug >= 2 {
+                               __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+                       }
+                       if yychar == yyEofCode {
+                               goto ret1
+                       }
+                       yychar = -1
+                       goto yynewstate /* try again in the same state */
+               }
+       }
+
+       /* reduction by production yyn */
+       if yyDebug >= 2 {
+               __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+       }
+
+       yynt := yyn
+       yypt := yyp
+       _ = yypt // guard against "declared and not used"
+
+       yyp -= yyR2[yyn]
+       // yyp is now the index of $0. Perform the default action. Iff the
+       // reduced production is Îµ, $1 is possibly out of range.
+       if yyp+1 >= len(yyS) {
+               nyys := make([]yySymType, len(yyS)*2)
+               copy(nyys, yyS)
+               yyS = nyys
+       }
+       yyVAL = yyS[yyp+1]
+
+       /* consult goto table to find next state */
+       yyn = yyR1[yyn]
+       yyg := yyPgo[yyn]
+       yyj := yyg + yyS[yyp].yys + 1
+
+       if yyj >= yyLast {
+               yystate = yyAct[yyg]
+       } else {
+               yystate = yyAct[yyj]
+               if yyChk[yystate] != -yyn {
+                       yystate = yyAct[yyg]
+               }
+       }
+       // dummy call; replaced with literal code
+       switch yynt {
+
+       case 3:
+               //line a.y:75
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+                               yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyS[yypt-1].sym.Type = LLAB
+                       yyS[yypt-1].sym.Value = int64(asm.PC)
+               }
+       case 5:
+               //line a.y:85
+               {
+                       yyS[yypt-3].sym.Type = LVAR
+                       yyS[yypt-3].sym.Value = yyS[yypt-1].lval
+               }
+       case 6:
+               //line a.y:90
+               {
+                       if yyS[yypt-3].sym.Value != yyS[yypt-1].lval {
+                               yyerror("redeclaration of %s", yyS[yypt-3].sym.Name)
+                       }
+                       yyS[yypt-3].sym.Value = yyS[yypt-1].lval
+               }
+       case 7:
+               //line a.y:97
+               {
+                       nosched = int(yyS[yypt-1].lval)
+               }
+       case 11:
+               //line a.y:109
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 12:
+               //line a.y:113
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 13:
+               //line a.y:117
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 14:
+               //line a.y:121
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 15:
+               //line a.y:125
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 16:
+               //line a.y:129
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 17:
+               //line a.y:136
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 18:
+               //line a.y:140
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 19:
+               //line a.y:144
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 20:
+               //line a.y:148
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 21:
+               //line a.y:152
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 22:
+               //line a.y:156
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 23:
+               //line a.y:163
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 24:
+               //line a.y:167
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 25:
+               //line a.y:171
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 26:
+               //line a.y:175
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 27:
+               //line a.y:182
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 28:
+               //line a.y:186
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 29:
+               //line a.y:193
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 30:
+               //line a.y:197
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 31:
+               //line a.y:201
+               {
+                       outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 32:
+               //line a.y:205
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 33:
+               //line a.y:209
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 34:
+               //line a.y:213
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+               }
+       case 35:
+               //line a.y:220
+               {
+                       outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 36:
+               //line a.y:224
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 37:
+               //line a.y:228
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 38:
+               //line a.y:238
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 39:
+               //line a.y:242
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 40:
+               //line a.y:246
+               {
+                       outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 41:
+               //line a.y:250
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 42:
+               //line a.y:254
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 43:
+               //line a.y:258
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 44:
+               //line a.y:262
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 45:
+               //line a.y:266
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 46:
+               //line a.y:270
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 47:
+               //line a.y:274
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 48:
+               //line a.y:278
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 49:
+               //line a.y:282
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 50:
+               //line a.y:286
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 51:
+               //line a.y:293
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 52:
+               //line a.y:300
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 53:
+               //line a.y:304
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 54:
+               //line a.y:311
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-0].addr)
+               }
+       case 55:
+               //line a.y:315
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 56:
+               //line a.y:323
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 57:
+               //line a.y:327
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 58:
+               //line a.y:331
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 59:
+               //line a.y:335
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 60:
+               //line a.y:339
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 61:
+               //line a.y:343
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 62:
+               //line a.y:347
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 63:
+               //line a.y:351
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 64:
+               //line a.y:360
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 65:
+               //line a.y:364
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 66:
+               //line a.y:368
+               {
+                       outcode(int(yyS[yypt-3].lval), &nullgen, NREG, &yyS[yypt-1].addr)
+               }
+       case 67:
+               //line a.y:372
+               {
+                       outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 68:
+               //line a.y:376
+               {
+                       outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 69:
+               //line a.y:380
+               {
+                       outcode(int(yyS[yypt-4].lval), &nullgen, NREG, &yyS[yypt-1].addr)
+               }
+       case 70:
+               //line a.y:384
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 71:
+               //line a.y:388
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 72:
+               //line a.y:392
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-1].addr)
+               }
+       case 73:
+               //line a.y:396
+               {
+                       outcode(int(yyS[yypt-3].lval), &nullgen, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 74:
+               //line a.y:400
+               {
+                       outcode(int(yyS[yypt-3].lval), &nullgen, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 75:
+               //line a.y:404
+               {
+                       outcode(int(yyS[yypt-5].lval), &nullgen, int(yyS[yypt-4].lval), &yyS[yypt-1].addr)
+               }
+       case 76:
+               //line a.y:408
+               {
+                       var g obj.Addr
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = yyS[yypt-4].lval
+                       outcode(int(yyS[yypt-5].lval), &g, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 77:
+               //line a.y:416
+               {
+                       var g obj.Addr
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = yyS[yypt-4].lval
+                       outcode(int(yyS[yypt-5].lval), &g, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 78:
+               //line a.y:424
+               {
+                       var g obj.Addr
+                       g = nullgen
+                       g.Type = D_CONST
+                       g.Offset = yyS[yypt-6].lval
+                       outcode(int(yyS[yypt-7].lval), &g, int(yyS[yypt-4].lval), &yyS[yypt-1].addr)
+               }
+       case 79:
+               //line a.y:435
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+               }
+       case 80:
+               //line a.y:439
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+               }
+       case 81:
+               //line a.y:443
+               {
+                       outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 82:
+               //line a.y:447
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+               }
+       case 83:
+               //line a.y:454
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 84:
+               //line a.y:458
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 85:
+               //line a.y:462
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].addr.Reg), &yyS[yypt-0].addr)
+               }
+       case 86:
+               //line a.y:466
+               {
+                       outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 87:
+               //line a.y:470
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 88:
+               //line a.y:474
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+               }
+       case 89:
+               //line a.y:481
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 90:
+               //line a.y:485
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 91:
+               //line a.y:489
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+               }
+       case 92:
+               //line a.y:493
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+               }
+       case 93:
+               //line a.y:500
+               {
+                       outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 94:
+               //line a.y:504
+               {
+                       outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 95:
+               //line a.y:508
+               {
+                       outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 96:
+               //line a.y:512
+               {
+                       outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 97:
+               //line a.y:519
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 98:
+               //line a.y:523
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 99:
+               //line a.y:531
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 100:
+               //line a.y:535
+               {
+                       outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 101:
+               //line a.y:539
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 102:
+               //line a.y:543
+               {
+                       outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+               }
+       case 103:
+               //line a.y:547
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 104:
+               //line a.y:551
+               {
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 105:
+               //line a.y:555
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &nullgen)
+               }
+       case 106:
+               //line a.y:562
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+               }
+       case 107:
+               //line a.y:566
+               {
+                       outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 108:
+               //line a.y:570
+               {
+                       outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 109:
+               //line a.y:574
+               {
+                       outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 110:
+               //line a.y:578
+               {
+                       outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+               }
+       case 111:
+               //line a.y:582
+               {
+                       outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &nullgen)
+               }
+       case 112:
+               //line a.y:589
+               {
+                       outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 113:
+               //line a.y:593
+               {
+                       outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+               }
+       case 114:
+               //line a.y:600
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+                               yyerror("arguments to PCDATA must be integer constants")
+                       }
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 115:
+               //line a.y:610
+               {
+                       if yyS[yypt-2].addr.Type != D_CONST {
+                               yyerror("index for FUNCDATA must be integer constant")
+                       }
+                       if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC && yyS[yypt-0].addr.Type != D_OREG {
+                               yyerror("value for FUNCDATA must be symbol reference")
+                       }
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 116:
+               //line a.y:623
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+               }
+       case 117:
+               //line a.y:630
+               {
+                       asm.Settext(yyS[yypt-2].addr.Sym)
+                       outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+               }
+       case 118:
+               //line a.y:635
+               {
+                       asm.Settext(yyS[yypt-4].addr.Sym)
+                       yyS[yypt-0].addr.Offset &= 0xffffffff
+                       yyS[yypt-0].addr.Offset |= -obj.ArgsSizeUnknown << 32
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 119:
+               //line a.y:642
+               {
+                       asm.Settext(yyS[yypt-6].addr.Sym)
+                       yyS[yypt-2].addr.Offset &= 0xffffffff
+                       yyS[yypt-2].addr.Offset |= (yyS[yypt-0].lval & 0xffffffff) << 32
+                       outcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].lval), &yyS[yypt-2].addr)
+               }
+       case 120:
+               //line a.y:652
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 121:
+               //line a.y:656
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 122:
+               //line a.y:660
+               {
+                       outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+               }
+       case 123:
+               //line a.y:667
+               {
+                       outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+               }
+       case 124:
+               //line a.y:673
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+               }
+       case 125:
+               //line a.y:679
+               {
+                       yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+                       yyVAL.addr = nullgen
+                       if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+                               yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+                       }
+                       yyVAL.addr.Type = D_BRANCH
+                       yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+               }
+       case 126:
+               //line a.y:691
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_REG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 127:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 128:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 129:
+               //line a.y:703
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SPR
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 130:
+               //line a.y:711
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CREG
+                       yyVAL.addr.Reg = NREG /* whole register */
+               }
+       case 131:
+               //line a.y:718
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SPR
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 132:
+               //line a.y:726
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_MSR
+               }
+       case 133:
+               //line a.y:733
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SPR
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 134:
+               //line a.y:739
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = int16(yyS[yypt-3].lval)
+                       yyVAL.addr.Offset = yyS[yypt-1].lval
+               }
+       case 135:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 136:
+               //line a.y:748
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FPSCR
+                       yyVAL.addr.Reg = NREG
+               }
+       case 137:
+               //line a.y:756
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FPSCR
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 138:
+               //line a.y:764
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 139:
+               //line a.y:770
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 140:
+               //line a.y:778
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 141:
+               //line a.y:784
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+               }
+       case 142:
+               //line a.y:792
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_REG
+                       yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+               }
+       case 143:
+               //line a.y:800
+               {
+                       var mb, me int
+                       var v uint32
+
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST
+                       mb = int(yyS[yypt-2].lval)
+                       me = int(yyS[yypt-0].lval)
+                       if mb < 0 || mb > 31 || me < 0 || me > 31 {
+                               yyerror("illegal mask start/end value(s)")
+                               mb = 0
+                               me = 0
+                       }
+                       if mb <= me {
+                               v = (^uint32(0) >> uint(mb)) & (^uint32(0) << uint(31-me))
+                       } else {
+                               v = (^uint32(0) >> uint(me+1)) & (^uint32(0) << uint(31-(mb-1)))
+                       }
+                       yyVAL.addr.Offset = int64(v)
+               }
+       case 144:
+               //line a.y:823
+               {
+                       yyVAL.addr = yyS[yypt-0].addr
+                       yyVAL.addr.Type = D_CONST
+               }
+       case 145:
+               //line a.y:828
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_SCONST
+                       yyVAL.addr.U.Sval = yyS[yypt-0].sval
+               }
+       case 146:
+               //line a.y:836
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = yyS[yypt-0].dval
+               }
+       case 147:
+               //line a.y:842
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_FCONST
+                       yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+               }
+       case 148:
+               //line a.y:849
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_CONST
+                       yyVAL.addr.Offset = yyS[yypt-0].lval
+               }
+       case 149:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 150:
+               //line a.y:858
+               {
+                       if yyVAL.lval < 0 || yyVAL.lval >= NREG {
+                               print("register value out of range\n")
+                       }
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 151:
+               //line a.y:867
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = 0
+               }
+       case 152:
+               //line a.y:874
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-3].lval)
+                       yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = 0
+               }
+       case 153:
+               yyVAL.addr = yyS[yypt-0].addr
+       case 154:
+               //line a.y:885
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 155:
+               //line a.y:894
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = nil
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 156:
+               //line a.y:902
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 157:
+               //line a.y:910
+               {
+                       yyVAL.addr = nullgen
+                       yyVAL.addr.Type = D_OREG
+                       yyVAL.addr.Name = D_STATIC
+                       yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 0)
+                       yyVAL.addr.Offset = yyS[yypt-3].lval
+               }
+       case 160:
+               //line a.y:922
+               {
+                       yyVAL.lval = 0
+               }
+       case 161:
+               //line a.y:926
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 162:
+               //line a.y:930
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 163:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 164:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 165:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 166:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 167:
+               //line a.y:942
+               {
+                       yyVAL.lval = yyS[yypt-0].sym.Value
+               }
+       case 168:
+               //line a.y:946
+               {
+                       yyVAL.lval = -yyS[yypt-0].lval
+               }
+       case 169:
+               //line a.y:950
+               {
+                       yyVAL.lval = yyS[yypt-0].lval
+               }
+       case 170:
+               //line a.y:954
+               {
+                       yyVAL.lval = ^yyS[yypt-0].lval
+               }
+       case 171:
+               //line a.y:958
+               {
+                       yyVAL.lval = yyS[yypt-1].lval
+               }
+       case 172:
+               yyVAL.lval = yyS[yypt-0].lval
+       case 173:
+               //line a.y:965
+               {
+                       yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+               }
+       case 174:
+               //line a.y:969
+               {
+                       yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+               }
+       case 175:
+               //line a.y:973
+               {
+                       yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+               }
+       case 176:
+               //line a.y:977
+               {
+                       yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+               }
+       case 177:
+               //line a.y:981
+               {
+                       yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+               }
+       case 178:
+               //line a.y:985
+               {
+                       yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+               }
+       case 179:
+               //line a.y:989
+               {
+                       yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+               }
+       case 180:
+               //line a.y:993
+               {
+                       yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+               }
+       case 181:
+               //line a.y:997
+               {
+                       yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+               }
+       case 182:
+               //line a.y:1001
+               {
+                       yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+               }
+       }
+       goto yystack /* stack new state and value */
+}
diff --git a/src/cmd/objwriter/main.go b/src/cmd/objwriter/main.go
new file mode 100644 (file)
index 0000000..c53089d
--- /dev/null
@@ -0,0 +1,411 @@
+// Copyright 2015 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.
+
+// Objwriter reads an object file description in an unspecified format
+// and writes a Go object file. It is invoked by parts of the toolchain
+// that have not yet been converted from C to Go and should not be
+// used otherwise.
+package main
+
+import (
+       "bufio"
+       "bytes"
+       "flag"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "log"
+       "math"
+       "os"
+       "runtime/pprof"
+       "strconv"
+       "strings"
+
+       "cmd/internal/obj"
+       "cmd/internal/obj/arm"
+       "cmd/internal/obj/i386"
+       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/x86"
+)
+
+var arch *obj.LinkArch
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
+var memprofile = flag.String("memprofile", "", "write memory profile to this file")
+
+func main() {
+       log.SetPrefix("goobj: ")
+       log.SetFlags(0)
+       flag.Parse()
+
+       if flag.NArg() == 1 && flag.Arg(0) == "ping" {
+               // old invocation from liblink, just testing that objwriter exists
+               return
+       }
+
+       if flag.NArg() != 4 {
+               fmt.Fprintf(os.Stderr, "usage: goobj infile objfile offset goarch\n")
+               os.Exit(2)
+       }
+
+       if *cpuprofile != "" {
+               f, err := os.Create(*cpuprofile)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               pprof.StartCPUProfile(f)
+               defer pprof.StopCPUProfile()
+       }
+       if *memprofile != "" {
+               f, err := os.Create(*memprofile)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               defer pprof.WriteHeapProfile(f)
+       }
+
+       switch flag.Arg(3) {
+       case "amd64":
+               arch = &x86.Linkamd64
+       case "amd64p32":
+               arch = &x86.Linkamd64p32
+       case "386":
+               // TODO(rsc): Move Link386 to package x86.
+               arch = &i386.Link386
+       case "arm":
+               arch = &arm.Linkarm
+       case "ppc64":
+               arch = &ppc64.Linkppc64
+       case "ppc64le":
+               arch = &ppc64.Linkppc64le
+       }
+
+       input()
+}
+
+const (
+       // must match liblink/objfilego.c
+       TypeEnd = iota
+       TypeCtxt
+       TypePlist
+       TypeSym
+       TypeProg
+       TypeAddr
+       TypeHist
+)
+
+var (
+       ctxt   *obj.Link
+       plists = map[int64]*obj.Plist{}
+       syms   = map[int64]*obj.LSym{}
+       progs  = map[int64]*obj.Prog{}
+       hists  = map[int64]*obj.Hist{}
+       undef  = map[interface{}]bool{}
+)
+
+func input() {
+       args := flag.Args()
+       ctxt = obj.Linknew(arch)
+       ctxt.Debugasm = 1
+       ctxt.Bso = obj.Binitw(os.Stdout)
+       defer obj.Bflush(ctxt.Bso)
+       ctxt.Diag = log.Fatalf
+       f, err := os.Open(args[0])
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       b := bufio.NewReaderSize(f, 1<<20)
+       if v := rdint(b); v != TypeCtxt {
+               log.Fatalf("invalid input - missing ctxt - got %d", v)
+       }
+       name := rdstring(b)
+       if name != ctxt.Arch.Name {
+               log.Fatalf("bad arch %s - want %s", name, ctxt.Arch.Name)
+       }
+
+       ctxt.Goarm = int32(rdint(b))
+       ctxt.Debugasm = int32(rdint(b))
+       ctxt.Trimpath = rdstring(b)
+       ctxt.Plist = rdplist(b)
+       ctxt.Plast = rdplist(b)
+       ctxt.Hist = rdhist(b)
+       ctxt.Ehist = rdhist(b)
+       for {
+               i := rdint(b)
+               if i < 0 {
+                       break
+               }
+               ctxt.Hash[i] = rdsym(b)
+       }
+       last := int64(TypeCtxt)
+
+Loop:
+       for {
+               t := rdint(b)
+               switch t {
+               default:
+                       log.Fatalf("unexpected input after type %d: %v", last, t)
+               case TypeEnd:
+                       break Loop
+               case TypePlist:
+                       readplist(b, rdplist(b))
+               case TypeSym:
+                       readsym(b, rdsym(b))
+               case TypeProg:
+                       readprog(b, rdprog(b))
+               case TypeHist:
+                       readhist(b, rdhist(b))
+               }
+               last = t
+       }
+
+       if len(undef) > 0 {
+               panic("missing definitions")
+       }
+
+       var buf bytes.Buffer
+       obuf := obj.Binitw(&buf)
+       obj.Writeobjdirect(ctxt, obuf)
+       obj.Bflush(obuf)
+
+       data, err := ioutil.ReadFile(args[1])
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       offset, err := strconv.Atoi(args[2])
+       if err != nil {
+               log.Fatalf("bad offset: %v", err)
+       }
+       if offset > len(data) {
+               log.Fatalf("offset too large: %v > %v", offset, len(data))
+       }
+
+       old := data[offset:]
+       if len(old) > 0 && !bytes.Equal(old, buf.Bytes()) {
+               out := strings.TrimSuffix(args[0], ".in") + ".out"
+               if err := ioutil.WriteFile(out, append(data[:offset:offset], buf.Bytes()...), 0666); err != nil {
+                       log.Fatal(err)
+               }
+               log.Fatalf("goobj produced different output:\n\toriginal: %s\n\tgoobj: %s", args[1], out)
+       }
+
+       if len(old) == 0 {
+               data = append(data, buf.Bytes()...)
+               if err := ioutil.WriteFile(args[1], data, 0666); err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
+
+func rdstring(b *bufio.Reader) string {
+       v := rdint(b)
+       buf := make([]byte, v)
+       io.ReadFull(b, buf)
+       return string(buf)
+}
+
+func rdint(b *bufio.Reader) int64 {
+       var v uint64
+       shift := uint(0)
+       for {
+               b, err := b.ReadByte()
+               if err != nil {
+                       log.Fatal(err)
+               }
+               v |= uint64(b&0x7F) << shift
+               shift += 7
+               if b&0x80 == 0 {
+                       break
+               }
+       }
+       return int64(v>>1) ^ int64(v<<63)>>63
+}
+
+func rdplist(b *bufio.Reader) *obj.Plist {
+       id := rdint(b)
+       if id == 0 {
+               return nil
+       }
+       pl := plists[id]
+       if pl == nil {
+               pl = new(obj.Plist)
+               plists[id] = pl
+               undef[pl] = true
+       }
+       return pl
+}
+
+func rdsym(b *bufio.Reader) *obj.LSym {
+       id := rdint(b)
+       if id == 0 {
+               return nil
+       }
+       sym := syms[id]
+       if sym == nil {
+               sym = new(obj.LSym)
+               syms[id] = sym
+               undef[sym] = true
+       }
+       return sym
+}
+
+func rdprog(b *bufio.Reader) *obj.Prog {
+       id := rdint(b)
+       if id == 0 {
+               return nil
+       }
+       prog := progs[id]
+       if prog == nil {
+               prog = new(obj.Prog)
+               prog.Ctxt = ctxt
+               progs[id] = prog
+               undef[prog] = true
+       }
+       return prog
+}
+
+func rdhist(b *bufio.Reader) *obj.Hist {
+       id := rdint(b)
+       if id == 0 {
+               return nil
+       }
+       h := hists[id]
+       if h == nil {
+               h = new(obj.Hist)
+               hists[id] = h
+               undef[h] = true
+       }
+       return h
+}
+
+func readplist(b *bufio.Reader, pl *obj.Plist) {
+       if !undef[pl] {
+               panic("double-def")
+       }
+       delete(undef, pl)
+       pl.Recur = int(rdint(b))
+       pl.Name = rdsym(b)
+       pl.Firstpc = rdprog(b)
+       pl.Link = rdplist(b)
+}
+
+func readsym(b *bufio.Reader, s *obj.LSym) {
+       if !undef[s] {
+               panic("double-def")
+       }
+       delete(undef, s)
+       s.Name = rdstring(b)
+       s.Extname = rdstring(b)
+       s.Type = int16(rdint(b))
+       s.Version = int16(rdint(b))
+       s.Dupok = uint8(rdint(b))
+       s.External = uint8(rdint(b))
+       s.Nosplit = uint8(rdint(b))
+       s.Reachable = uint8(rdint(b))
+       s.Cgoexport = uint8(rdint(b))
+       s.Special = uint8(rdint(b))
+       s.Stkcheck = uint8(rdint(b))
+       s.Hide = uint8(rdint(b))
+       s.Leaf = uint8(rdint(b))
+       s.Fnptr = uint8(rdint(b))
+       s.Seenglobl = uint8(rdint(b))
+       s.Onlist = uint8(rdint(b))
+       s.Symid = int16(rdint(b))
+       s.Dynid = int32(rdint(b))
+       s.Sig = int32(rdint(b))
+       s.Plt = int32(rdint(b))
+       s.Got = int32(rdint(b))
+       s.Align = int32(rdint(b))
+       s.Elfsym = int32(rdint(b))
+       s.Args = int32(rdint(b))
+       s.Locals = int32(rdint(b))
+       s.Value = rdint(b)
+       s.Size = rdint(b)
+       s.Hash = rdsym(b)
+       s.Allsym = rdsym(b)
+       s.Next = rdsym(b)
+       s.Sub = rdsym(b)
+       s.Outer = rdsym(b)
+       s.Gotype = rdsym(b)
+       s.Reachparent = rdsym(b)
+       s.Queue = rdsym(b)
+       s.File = rdstring(b)
+       s.Dynimplib = rdstring(b)
+       s.Dynimpvers = rdstring(b)
+       s.Text = rdprog(b)
+       s.Etext = rdprog(b)
+       n := int(rdint(b))
+       if n > 0 {
+               s.P = make([]byte, n)
+               io.ReadFull(b, s.P)
+       }
+       s.R = make([]obj.Reloc, int(rdint(b)))
+       for i := range s.R {
+               r := &s.R[i]
+               r.Off = int32(rdint(b))
+               r.Siz = uint8(rdint(b))
+               r.Done = uint8(rdint(b))
+               r.Type = int32(rdint(b))
+               r.Add = rdint(b)
+               r.Xadd = rdint(b)
+               r.Sym = rdsym(b)
+               r.Xsym = rdsym(b)
+       }
+}
+
+func readprog(b *bufio.Reader, p *obj.Prog) {
+       if !undef[p] {
+               panic("double-def")
+       }
+       delete(undef, p)
+       p.Pc = rdint(b)
+       p.Lineno = int32(rdint(b))
+       p.Link = rdprog(b)
+       p.As = int16(rdint(b))
+       p.Reg = uint8(rdint(b))
+       p.Scond = uint8(rdint(b))
+       p.Width = int8(rdint(b))
+       readaddr(b, &p.From)
+       readaddr(b, &p.From3)
+       readaddr(b, &p.To)
+}
+
+func readaddr(b *bufio.Reader, a *obj.Addr) {
+       if rdint(b) != TypeAddr {
+               log.Fatal("out of sync")
+       }
+       a.Offset = rdint(b)
+       a.U.Dval = rdfloat(b)
+       buf := make([]byte, 8)
+       io.ReadFull(b, buf)
+       a.U.Sval = string(buf)
+       a.U.Branch = rdprog(b)
+       a.Sym = rdsym(b)
+       a.Gotype = rdsym(b)
+       a.Type = int16(rdint(b))
+       a.Index = uint8(rdint(b))
+       a.Scale = int8(rdint(b))
+       a.Reg = int8(rdint(b))
+       a.Name = int8(rdint(b))
+       a.Class = int8(rdint(b))
+       a.Etype = uint8(rdint(b))
+       a.Offset2 = int32(rdint(b))
+       a.Width = rdint(b)
+}
+
+func readhist(b *bufio.Reader, h *obj.Hist) {
+       if !undef[h] {
+               panic("double-def")
+       }
+       delete(undef, h)
+       h.Link = rdhist(b)
+       h.Name = rdstring(b)
+       h.Line = int32(rdint(b))
+       h.Offset = int32(rdint(b))
+}
+
+func rdfloat(b *bufio.Reader) float64 {
+       return math.Float64frombits(uint64(rdint(b)))
+}
index 2d4a800dd1930f028aa75232c4b3aa637b7c2b2a..68b94d6114ed3eccd5c639b3cf0da65b1320e075 100644 (file)
@@ -52,8 +52,20 @@ getgo386(void)
        return defgetenv("GO386", GO386);
 }
 
-char *
+char*
 getgoextlinkenabled(void)
 {
        return GO_EXTLINK_ENABLED;
 }
+
+char*
+getgohostarch(void)
+{
+       return GOHOSTARCH;
+}
+
+char*
+getgohostos(void)
+{
+       return GOHOSTOS;
+}
index 87875b42dbdefd26a977cbc60636a65f3b4f521a..e3e1c25710d1beb624add3f7c85a6bab74a899ac 100644 (file)
@@ -19,7 +19,7 @@ runcmd(char **argv)
        WinRune *r;
        STARTUPINFOW si;
        PROCESS_INFORMATION pi;
-       DWORD code;
+       DWORD code, lasterr;
 
        fmtstrinit(&fmt);
        for(i=0; argv[i]; i++) {
@@ -63,18 +63,24 @@ runcmd(char **argv)
        si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 
        if(!CreateProcessW(nil, r, nil, nil, TRUE, 0, nil, nil, &si, &pi)) {
+               werrstr("CreateProcess failed: errno=%d", (int)GetLastError());
                free(r);
                return -1;
        }
 
        free(r);
-       if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0)
+       if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0) {
+               werrstr("WaitForMultipleObjects failed: errno=%d", (int)GetLastError());
                return -1;
+       }
        i = GetExitCodeProcess(pi.hProcess, &code);
+       lasterr = GetLastError();
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
-       if(!i)
+       if(!i) {
+               werrstr("GetExitCodeProcess failed: errno=%d", (int)lasterr);
                return -1;
+       }
        if(code != 0) {
                werrstr("unsuccessful exit status: %d", (int)code);
                return -1;
index c01160af7e50ff90d46457dab41105acdaa33ef5..99f5e97607b4757629b0518a17a18e0ad09e7596 100644 (file)
@@ -119,11 +119,52 @@ static char *rdstring(Biobuf*);
 static void rddata(Biobuf*, uchar**, int*);
 static LSym *rdsym(Link*, Biobuf*, char*);
 
+void   writeobjdirect(Link *ctxt, Biobuf *b);
+
+void   writeobjgo1(Link*, char*);
+void   writeobjgo2(Link*, char*, int64);
+
+extern char *outfile;
+
+void
+writeobj(Link *ctxt, Biobuf *b)
+{
+       vlong start;
+       char *env;
+
+       // If $GOOBJ > 0, invoke the Go version of the liblink
+       // output routines via a subprocess.
+       // If $GOOBJ == 1, copy that subprocess's output to
+       // the actual output file.
+       // If $GOOBJ >= 2, generate output using the usual C version
+       // but then check that the subprocess wrote the same bytes.
+       // $GOOBJ is a temporary setting for the transition to a
+       // Go liblink back end. Once the C liblink back ends are deleted,
+       // we will hard code the GOOBJ=1 behavior.
+       env = getenv("GOOBJ");
+       if(env == nil)
+               env = "0";
+       if(atoi(env) == 0) {
+               writeobjdirect(ctxt, b);
+               return;
+       }
+
+       Bflush(b);
+       start = Boffset(b);
+       writeobjgo1(ctxt, outfile);
+       if(atoi(env) > 1) {
+               writeobjdirect(ctxt, b);
+               Bflush(b);
+       }
+       writeobjgo2(ctxt, outfile, start);
+       Bseek(b, 0, 2);
+}
+
 // The Go and C compilers, and the assembler, call writeobj to write
 // out a Go object file.  The linker does not call this; the linker
 // does not write out object files.
 void
-writeobj(Link *ctxt, Biobuf *b)
+writeobjdirect(Link *ctxt, Biobuf *b)
 {
        int flag, found;
        Hist *h;
diff --git a/src/liblink/objfilego.c b/src/liblink/objfilego.c
new file mode 100644 (file)
index 0000000..4060193
--- /dev/null
@@ -0,0 +1,340 @@
+// Copyright 2015 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.
+
+// Writing of internal program representation to a serialized form
+// so that the Go translation of these routines can do the actual
+// program layout.
+// The serialized form and this code support the piecewise transition
+// from C to Go and will be removed along with the rest of the C code
+// when it is no longer needed.
+// There has been no attempt to make it particularly efficient, nor will there be.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+
+/*c2go
+
+char *mktempdir(void);
+int runcmd(char**);
+void removeall(char*);
+*/
+
+static void printtype(Link*, Biobuf*, int);
+static void printsym(Link*, Biobuf*, LSym*);
+static void printprog(Link*, Biobuf*, Prog*);
+static void printaddr(Link*, Biobuf*, Addr*);
+static void printhist(Link*, Biobuf*, Hist*);
+static void printint(Link*, Biobuf*, int64);
+static void printstr(Link*, Biobuf*, char*);
+static void printptr(Link*, Biobuf*, void*);
+
+#undef waitpid
+
+enum
+{
+       TypeEnd = 0,
+       TypeCtxt,
+       TypePlist,
+       TypeSym,
+       TypeProg,
+       TypeAddr,
+       TypeHist,
+};
+
+void
+writeobjgo1(Link *ctxt, char *outfile)
+{
+       int i;
+       char *p;
+       Biobuf *bw;
+       Plist *pl;
+       
+       p = smprint("%s.goliblink.in", outfile);
+       bw = Bopen(p, OWRITE);
+       if(bw == nil)
+               sysfatal("writing liblinktest input: %r");
+
+       printtype(ctxt, bw, TypeCtxt);
+       printstr(ctxt, bw, ctxt->arch->name);
+       printint(ctxt, bw, ctxt->goarm);
+       printint(ctxt, bw, ctxt->debugasm);
+       printstr(ctxt, bw, ctxt->trimpath);
+       printptr(ctxt, bw, ctxt->plist);
+       printptr(ctxt, bw, ctxt->plast);
+       printptr(ctxt, bw, ctxt->hist);
+       printptr(ctxt, bw, ctxt->ehist);
+       for(i = 0; i < LINKHASH; i++) {
+               if(ctxt->hash[i] != nil) {
+                       printint(ctxt, bw, i);
+                       printptr(ctxt, bw, ctxt->hash[i]);
+               }
+       }
+       printint(ctxt, bw, -1);
+
+       printhist(ctxt, bw, ctxt->hist);
+       printhist(ctxt, bw, ctxt->ehist);
+
+       for(pl=ctxt->plist; pl != nil; pl = pl->link) {
+               printtype(ctxt, bw, TypePlist);
+               printptr(ctxt, bw, pl);
+               printint(ctxt, bw, pl->recur);
+               printptr(ctxt, bw, pl->name);
+               printptr(ctxt, bw, pl->firstpc);
+               printptr(ctxt, bw, pl->link);
+               printsym(ctxt, bw, pl->name);
+               printprog(ctxt, bw, pl->firstpc);
+       }
+       
+       for(i = 0; i < LINKHASH; i++)
+               printsym(ctxt, bw, ctxt->hash[i]);
+
+       printtype(ctxt, bw, TypeEnd);
+       Bterm(bw);
+}
+
+void
+writeobjgo2(Link *ctxt, char *outfile, int64 offset)
+{
+       char *p, *env, *prog, *cmd[10];
+       char offsetbuf[20];
+       
+       USED(ctxt);
+
+       env = getenv("GOOBJWRITER");
+       if(env != nil && env[0] != '\0')
+               prog = env;
+       else
+               prog = smprint("%s/pkg/tool/%s_%s/objwriter", getgoroot(), getgohostos(), getgohostarch());
+
+       p = smprint("%s.goliblink.in", outfile);
+       
+       snprint(offsetbuf, sizeof offsetbuf, "%lld", offset);
+       
+       cmd[0] = prog;
+       cmd[1] = p;
+       cmd[2] = outfile;
+       cmd[3] = offsetbuf;
+       cmd[4] = ctxt->arch->name;
+       cmd[5] = nil;
+       if(runcmd(cmd) < 0)
+               sysfatal("running %s: %r", prog);
+
+       env = getenv("GOOBJ");
+       if(env == nil || atoi(env) <= 2)
+               remove(p);
+}
+
+static void
+printtype(Link *ctxt, Biobuf *bw, int t)
+{
+       printint(ctxt, bw, t);
+}
+
+static void
+printint(Link *ctxt, Biobuf *bw, int64 v)
+{
+       uint64 u;
+       
+       USED(ctxt);
+
+       u = (uint64)(v<<1) ^ (uint64)(v>>63);
+       while(u >= 0x80) {
+               Bputc(bw, u&0x7F | 0x80);
+               u >>= 7;
+       }
+       Bputc(bw, u);
+}
+
+static void
+printstr(Link *ctxt, Biobuf *bw, char *s)
+{
+       if(s == nil)
+               s = "";
+       printint(ctxt, bw, strlen(s));
+       Bwrite(bw, s, strlen(s));
+}
+
+static void
+printptr(Link *ctxt, Biobuf *bw, void *v)
+{
+       printint(ctxt, bw, (int64)(uintptr)v);
+}
+
+static void
+printsym(Link *ctxt, Biobuf *bw, LSym *s)
+{
+       int i;
+       Reloc *r;
+
+       if(s == nil || s->printed)
+               return;
+       s->printed = 1;
+       printtype(ctxt, bw, TypeSym);
+       printptr(ctxt, bw, s);
+       printstr(ctxt, bw, s->name);
+       printstr(ctxt, bw, s->extname);
+       printint(ctxt, bw, s->type);
+       printint(ctxt, bw, s->version);
+       printint(ctxt, bw, s->dupok);
+       printint(ctxt, bw, s->external);
+       printint(ctxt, bw, s->nosplit);
+       printint(ctxt, bw, s->reachable);
+       printint(ctxt, bw, s->cgoexport);
+       printint(ctxt, bw, s->special);
+       printint(ctxt, bw, s->stkcheck);
+       printint(ctxt, bw, s->hide);
+       printint(ctxt, bw, s->leaf);
+       printint(ctxt, bw, s->fnptr);
+       printint(ctxt, bw, s->seenglobl);
+       printint(ctxt, bw, s->onlist);
+       printint(ctxt, bw, s->symid);
+       printint(ctxt, bw, s->dynid);
+       printint(ctxt, bw, s->sig);
+       printint(ctxt, bw, s->plt);
+       printint(ctxt, bw, s->got);
+       printint(ctxt, bw, s->align);
+       printint(ctxt, bw, s->elfsym);
+       printint(ctxt, bw, s->args);
+       printint(ctxt, bw, s->locals);
+       printint(ctxt, bw, s->value);
+       printint(ctxt, bw, s->size);
+       printptr(ctxt, bw, s->hash);
+       printptr(ctxt, bw, s->allsym);
+       printptr(ctxt, bw, s->next);
+       printptr(ctxt, bw, s->sub);
+       printptr(ctxt, bw, s->outer);
+       printptr(ctxt, bw, s->gotype);
+       printptr(ctxt, bw, s->reachparent);
+       printptr(ctxt, bw, s->queue);
+       printstr(ctxt, bw, s->file);
+       printstr(ctxt, bw, s->dynimplib);
+       printstr(ctxt, bw, s->dynimpvers);
+       printptr(ctxt, bw, s->text);
+       printptr(ctxt, bw, s->etext);
+       printint(ctxt, bw, s->np);
+       Bwrite(bw, s->p, s->np);
+       printint(ctxt, bw, s->nr);
+       for(i=0; i<s->nr; i++) {
+               r = s->r+i;
+               printint(ctxt, bw, r->off);
+               printint(ctxt, bw, r->siz);
+               printint(ctxt, bw, r->done);
+               printint(ctxt, bw, r->type);
+               printint(ctxt, bw, r->add);
+               printint(ctxt, bw, r->xadd);
+               printptr(ctxt, bw, r->sym);
+               printptr(ctxt, bw, r->xsym);
+       }
+       
+       printsym(ctxt, bw, s->hash);
+       printsym(ctxt, bw, s->allsym);
+       printsym(ctxt, bw, s->next);
+       printsym(ctxt, bw, s->sub);
+       printsym(ctxt, bw, s->outer);
+       printsym(ctxt, bw, s->gotype);
+       printsym(ctxt, bw, s->reachparent);
+       printsym(ctxt, bw, s->queue);
+       printprog(ctxt, bw, s->text);
+       printprog(ctxt, bw, s->etext);
+       for(i=0; i<s->nr; i++) {
+               r = s->r+i;
+               printsym(ctxt, bw, r->sym);
+               printsym(ctxt, bw, r->xsym);
+       }
+}
+
+static void
+printprog(Link *ctxt, Biobuf *bw, Prog *p0)
+{
+       Prog *p, *q;
+
+       for(p = p0; p != nil && !p->printed; p=p->link) {
+               p->printed = 1;
+       
+               printtype(ctxt, bw, TypeProg);
+               printptr(ctxt, bw, p);
+               printint(ctxt, bw, p->pc);
+               printint(ctxt, bw, p->lineno);
+               printptr(ctxt, bw, p->link);
+               printint(ctxt, bw, p->as);
+               printint(ctxt, bw, p->reg);
+               printint(ctxt, bw, p->scond);
+               printint(ctxt, bw, p->width);
+               printaddr(ctxt, bw, &p->from);
+               printaddr(ctxt, bw, &p->from3);
+               printaddr(ctxt, bw, &p->to);
+               printsym(ctxt, bw, p->from.sym);
+               printsym(ctxt, bw, p->from.gotype);
+               printsym(ctxt, bw, p->to.sym);
+               printsym(ctxt, bw, p->to.gotype);
+       }
+       
+       q = p;
+       for(p=p0; p!=q; p=p->link) {
+               if(p->from.type == TYPE_BRANCH)
+                       printprog(ctxt, bw, p->from.u.branch);
+               if(p->to.type == TYPE_BRANCH)
+                       printprog(ctxt, bw, p->to.u.branch);
+       }
+}
+
+static void
+printaddr(Link *ctxt, Biobuf *bw, Addr *a)
+{
+       static char zero[8];
+
+       printtype(ctxt, bw, TypeAddr);
+       printint(ctxt, bw, a->offset);
+       if(a->type == TYPE_FCONST) {
+               uint64 u;
+               float64 f;
+               f = a->u.dval;
+               memmove(&u, &f, 8);
+               printint(ctxt, bw, u);
+       } else
+               printint(ctxt, bw, 0);
+       if(a->type == TYPE_SCONST)
+               Bwrite(bw, a->u.sval, 8);
+       else
+               Bwrite(bw, zero, 8);
+       if(a->type == TYPE_BRANCH)
+               printptr(ctxt, bw, a->u.branch);
+       else    
+               printptr(ctxt, bw, nil);
+       printptr(ctxt, bw, a->sym);
+       printptr(ctxt, bw, a->gotype);
+       printint(ctxt, bw, a->type);
+       printint(ctxt, bw, a->index);
+       printint(ctxt, bw, a->scale);
+       printint(ctxt, bw, a->reg);
+       printint(ctxt, bw, a->name);
+       printint(ctxt, bw, a->class);
+       printint(ctxt, bw, a->etype);
+       if(a->type == TYPE_TEXTSIZE)
+               printint(ctxt, bw, a->u.argsize);
+       else
+               printint(ctxt, bw, 0);
+       printint(ctxt, bw, a->width);
+}
+
+static void
+printhist(Link *ctxt, Biobuf *bw, Hist *h)
+{
+       if(h == nil || h->printed)
+               return;
+       h->printed = 1;
+
+       printtype(ctxt, bw, TypeHist);
+       printptr(ctxt, bw, h);
+       printptr(ctxt, bw, h->link);
+       if(h->name == nil)
+               printstr(ctxt, bw, "<pop>");
+       else
+               printstr(ctxt, bw, h->name);
+       printint(ctxt, bw, h->line);
+       printint(ctxt, bw, h->offset);
+       printhist(ctxt, bw, h->link);
+}
index bf83ee643f38378b1836f54fbf70472ef348c681..215fedd6eefaf45a5512f29830d2373eda89e924 100755 (executable)
@@ -138,7 +138,6 @@ if [ "$1" = "--dist-tool" ]; then
        exit 0
 fi
 
-echo "##### Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
 buildall="-a"
 if [ "$1" = "--no-clean" ]; then
        buildall=""
@@ -147,7 +146,6 @@ fi
 ./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap
 # Delay move of dist tool to now, because bootstrap may clear tool directory.
 mv cmd/dist/dist "$GOTOOLDIR"/dist
-"$GOTOOLDIR"/go_bootstrap clean -i std
 echo
 
 if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
index fab9c88ff6e6f243168549e24e6dcbb667953caa..ba3469e69e08832134a2f97160bbf8d870276b81 100644 (file)
@@ -71,14 +71,12 @@ echo.
 if x%1==x--dist-tool goto copydist
 if x%2==x--dist-tool goto copydist
 
-echo ##### Building compilers and Go bootstrap tool.
 set buildall=-a
 if x%1==x--no-clean set buildall=
 .\cmd\dist\dist bootstrap %buildall% -v
 if errorlevel 1 goto fail
 :: Delay move of dist tool to now, because bootstrap cleared tool directory.
 move .\cmd\dist\dist.exe "%GOTOOLDIR%\dist.exe"
-"%GOTOOLDIR%\go_bootstrap" clean -i std
 echo.
 
 if not %GOHOSTARCH% == %GOARCH% goto localbuild
index 7d57c25ff5fdb5fc9b22325e547a54616b7e5081..f4302739f7e5ae14d8ac0d7d482ac6cc52dd8670 100755 (executable)
@@ -69,14 +69,12 @@ if(~ $1 --dist-tool){
        exit
 }
 
-echo '# Building compilers and Go bootstrap tool for host,' $GOHOSTOS/$GOHOSTARCH^.
 buildall = -a
 if(~ $1 --no-clean)
        buildall = ()
 ./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
 # Delay move of dist tool to now, because bootstrap may clear tool directory.
 mv cmd/dist/dist $GOTOOLDIR/dist
-$GOTOOLDIR/go_bootstrap clean -i std
 echo
 
 # Run only one process at a time on 9vx.