cmd/internal/obj/mips: copy cmd/internal/obj/ppc64

Just a mechanical copy with filename renames, no code changes.
This is to reduce code difference when adding the mips64 port.

Change-Id: Id06e975f414a7b09f4827167b30813b228a3bfae
Reviewed-on: https://go-review.googlesource.com/14323
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/cmd/internal/obj/mips/a.out.go b/src/cmd/internal/obj/mips/a.out.go
new file mode 100644
index 0000000..3028b6c
--- /dev/null
+++ b/src/cmd/internal/obj/mips/a.out.go
@@ -0,0 +1,538 @@
+// 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
+
+import "cmd/internal/obj"
+
+//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p ppc64
+
+/*
+ * powerpc 64
+ */
+const (
+	NSNAME = 8
+	NSYM   = 50
+	NREG   = 32 /* number of general registers */
+	NFREG  = 32 /* number of floating point registers */
+)
+
+const (
+	REG_R0 = obj.RBasePPC64 + iota
+	REG_R1
+	REG_R2
+	REG_R3
+	REG_R4
+	REG_R5
+	REG_R6
+	REG_R7
+	REG_R8
+	REG_R9
+	REG_R10
+	REG_R11
+	REG_R12
+	REG_R13
+	REG_R14
+	REG_R15
+	REG_R16
+	REG_R17
+	REG_R18
+	REG_R19
+	REG_R20
+	REG_R21
+	REG_R22
+	REG_R23
+	REG_R24
+	REG_R25
+	REG_R26
+	REG_R27
+	REG_R28
+	REG_R29
+	REG_R30
+	REG_R31
+
+	REG_F0
+	REG_F1
+	REG_F2
+	REG_F3
+	REG_F4
+	REG_F5
+	REG_F6
+	REG_F7
+	REG_F8
+	REG_F9
+	REG_F10
+	REG_F11
+	REG_F12
+	REG_F13
+	REG_F14
+	REG_F15
+	REG_F16
+	REG_F17
+	REG_F18
+	REG_F19
+	REG_F20
+	REG_F21
+	REG_F22
+	REG_F23
+	REG_F24
+	REG_F25
+	REG_F26
+	REG_F27
+	REG_F28
+	REG_F29
+	REG_F30
+	REG_F31
+
+	REG_CR0
+	REG_CR1
+	REG_CR2
+	REG_CR3
+	REG_CR4
+	REG_CR5
+	REG_CR6
+	REG_CR7
+
+	REG_MSR
+	REG_FPSCR
+	REG_CR
+
+	REG_SPECIAL = REG_CR0
+
+	REG_SPR0 = obj.RBasePPC64 + 1024 // first of 1024 registers
+	REG_DCR0 = obj.RBasePPC64 + 2048 // first of 1024 registers
+
+	REG_XER = REG_SPR0 + 1
+	REG_LR  = REG_SPR0 + 8
+	REG_CTR = REG_SPR0 + 9
+
+	REGZERO  = REG_R0 /* set to zero */
+	REGSP    = REG_R1
+	REGSB    = REG_R2
+	REGRET   = REG_R3
+	REGARG   = -1      /* -1 disables passing the first argument in register */
+	REGRT1   = REG_R3  /* reserved for runtime, duffzero and duffcopy */
+	REGRT2   = REG_R4  /* reserved for runtime, duffcopy */
+	REGMIN   = REG_R7  /* register variables allocated from here to REGMAX */
+	REGCTXT  = REG_R11 /* context for closures */
+	REGTLS   = REG_R13 /* C ABI TLS base pointer */
+	REGMAX   = REG_R27
+	REGEXT   = REG_R30 /* external registers allocated from here down */
+	REGG     = REG_R30 /* G */
+	REGTMP   = REG_R31 /* used by the linker */
+	FREGRET  = REG_F0
+	FREGMIN  = REG_F17 /* first register variable */
+	FREGMAX  = REG_F26 /* last register variable for 9g only */
+	FREGEXT  = REG_F26 /* first external register */
+	FREGCVI  = REG_F27 /* floating conversion constant */
+	FREGZERO = REG_F28 /* both float and double */
+	FREGHALF = REG_F29 /* double */
+	FREGONE  = REG_F30 /* double */
+	FREGTWO  = REG_F31 /* double */
+)
+
+/*
+ * 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 (
+	/* mark flags */
+	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 /* special processor register */
+	C_ZCON
+	C_SCON   /* 16 bit signed */
+	C_UCON   /* 32 bit signed, low 16 bits 0 */
+	C_ADDCON /* -0x8000 <= v < 0 */
+	C_ANDCON /* 0 < v <= 0xFFFF */
+	C_LCON   /* other 32 */
+	C_DCON   /* other 64 (could subdivide further) */
+	C_SACON  /* $n(REG) where n <= int16 */
+	C_SECON
+	C_LACON /* $n(REG) where int16 < n <= int32 */
+	C_LECON
+	C_DACON /* $n(REG) where int32 < n */
+	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_TEXTSIZE
+
+	C_NCLASS /* must be the last */
+)
+
+const (
+	AADD = obj.ABasePPC64 + obj.A_ARCHSPECIFIC + iota
+	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
+	ABLE
+	ABLT
+	ABNE
+	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
+	AWORD
+
+	ARFCI
+
+	/* optional on 32-bit */
+	AFRES
+	AFRESCC
+	AFRSQRTE
+	AFRSQRTECC
+	AFSEL
+	AFSELCC
+	AFSQRT
+	AFSQRTCC
+	AFSQRTS
+	AFSQRTSCC
+
+	/* 64-bit */
+
+	ACNTLZD
+	ACNTLZDCC
+	ACMPW /* CMP with L=0 */
+	ACMPWU
+	ADIVD
+	ADIVDCC
+	ADIVDVCC
+	ADIVDV
+	ADIVDU
+	ADIVDUCC
+	ADIVDUVCC
+	ADIVDUV
+	AEXTSW
+	AEXTSWCC
+	/* AFCFIW; AFCFIWCC */
+	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
+
+	/* 64-bit pseudo operation */
+	ADWORD
+	AREMD
+	AREMDCC
+	AREMDV
+	AREMDVCC
+	AREMDU
+	AREMDUCC
+	AREMDUV
+	AREMDUVCC
+
+	/* more 64-bit operations */
+	AHRFID
+
+	ALAST
+
+	// aliases
+	ABR = obj.AJMP
+	ABL = obj.ACALL
+)
diff --git a/src/cmd/internal/obj/mips/anames.go b/src/cmd/internal/obj/mips/anames.go
new file mode 100644
index 0000000..1ae7a52
--- /dev/null
+++ b/src/cmd/internal/obj/mips/anames.go
@@ -0,0 +1,300 @@
+// Generated by stringer -i a.out.go -o anames.go -p ppc64
+// Do not edit.
+
+package ppc64
+
+import "cmd/internal/obj"
+
+var Anames = []string{
+	obj.A_ARCHSPECIFIC: "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",
+	"BLE",
+	"BLT",
+	"BNE",
+	"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",
+	"WORD",
+	"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",
+	"LAST",
+}
diff --git a/src/cmd/internal/obj/mips/anames0.go b/src/cmd/internal/obj/mips/anames0.go
new file mode 100644
index 0000000..b48e516
--- /dev/null
+++ b/src/cmd/internal/obj/mips/anames0.go
@@ -0,0 +1,40 @@
+package ppc64
+
+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",
+	"TEXTSIZE",
+	"NCLASS",
+}
diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go
new file mode 100644
index 0000000..2955a00
--- /dev/null
+++ b/src/cmd/internal/obj/mips/asm0.go
@@ -0,0 +1,3247 @@
+// 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"
+	"encoding/binary"
+	"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 int16
+}
+
+var optab = []Optab{
+	Optab{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
+	Optab{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
+	Optab{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
+	Optab{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 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{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
+	Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+	Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+	Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
+	Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+	Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+	Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+
+	Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+}
+
+type Oprang struct {
+	start []Optab
+	stop  []Optab
+}
+
+var oprange [ALAST & obj.AMask]Oprang
+
+var xcmp [C_NCLASS][C_NCLASS]uint8
+
+func span9(ctxt *obj.Link, cursym *obj.LSym) {
+	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 + 8)
+
+	if oprange[AANDN&obj.AMask].start == nil {
+		buildop(ctxt)
+	}
+
+	c := int64(0)
+	p.Pc = c
+
+	var m int
+	var o *Optab
+	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 != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.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
+
+	var otxt int64
+	var q *obj.Prog
+	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 = obj.TYPE_BRANCH
+					q.Pcond = p.Pcond
+					p.Pcond = q
+					q = ctxt.NewProg()
+					q.Link = p.Link
+					p.Link = q
+					q.As = ABR
+					q.To.Type = obj.TYPE_BRANCH
+					q.Pcond = q.Link.Link
+
+					//addnop(p->link);
+					//addnop(p);
+					bflag = 1
+				}
+			}
+
+			m = int(o.size)
+			if m == 0 {
+				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.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
+	var i int32
+	var out [6]uint32
+	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) bool {
+	return int64(int32(v)) == v
+}
+
+func isuint32(v uint64) bool {
+	return uint64(uint32(v)) == v
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+	switch a.Type {
+	case obj.TYPE_NONE:
+		return C_NONE
+
+	case obj.TYPE_REG:
+		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
+			return C_REG
+		}
+		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
+			return C_FREG
+		}
+		if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR {
+			return C_CREG
+		}
+		if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 {
+			switch a.Reg {
+			case REG_LR:
+				return C_LR
+
+			case REG_XER:
+				return C_XER
+
+			case REG_CTR:
+				return C_CTR
+			}
+
+			return C_SPR
+		}
+
+		if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 {
+			return C_SPR
+		}
+		if a.Reg == REG_FPSCR {
+			return C_FPSCR
+		}
+		if a.Reg == REG_MSR {
+			return C_MSR
+		}
+		return C_GOK
+
+	case obj.TYPE_MEM:
+		switch a.Name {
+		case obj.NAME_EXTERN,
+			obj.NAME_STATIC:
+			if a.Sym == nil {
+				break
+			}
+			ctxt.Instoffset = a.Offset
+			if a.Sym != nil { // use relocation
+				return C_ADDR
+			}
+			return C_LEXT
+
+		case obj.NAME_AUTO:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SAUTO
+			}
+			return C_LAUTO
+
+		case obj.NAME_PARAM:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SAUTO
+			}
+			return C_LAUTO
+
+		case obj.NAME_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 obj.TYPE_TEXTSIZE:
+		return C_TEXTSIZE
+
+	case obj.TYPE_CONST,
+		obj.TYPE_ADDR:
+		switch a.Name {
+		case obj.TYPE_NONE:
+			ctxt.Instoffset = a.Offset
+			if a.Reg != 0 {
+				if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
+					return C_SACON
+				}
+				if isint32(ctxt.Instoffset) {
+					return C_LACON
+				}
+				return C_DACON
+			}
+
+			goto consize
+
+		case obj.NAME_EXTERN,
+			obj.NAME_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 obj.NAME_AUTO:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SACON
+			}
+			return C_LACON
+
+		case obj.NAME_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)) { /* && (instoffset & (1<<31)) == 0) */
+				return C_UCON
+			}
+			if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
+				return C_LCON
+			}
+			return C_DCON
+		}
+
+		if ctxt.Instoffset >= -0x8000 {
+			return C_ADDCON
+		}
+		if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
+			return C_UCON
+		}
+		if isint32(ctxt.Instoffset) {
+			return C_LCON
+		}
+		return C_DCON
+
+	case obj.TYPE_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 {
+	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 := C_NONE + 1
+	if p.From3 != nil {
+		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 != 0 {
+		a2 = C_REG
+	}
+
+	//print("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4);
+	r0 := p.As & obj.AMask
+
+	o := oprange[r0].start
+	if o == nil {
+		o = oprange[r0].stop /* just generate an error */
+	}
+	e := oprange[r0].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", obj.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 {
+	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 opset(a, b0 int16) {
+	oprange[a&obj.AMask] = oprange[b0]
+}
+
+func buildop(ctxt *obj.Link) {
+	var n 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 != obj.AXXX; n++ {
+	}
+	sort.Sort(ocmp(optab[:n]))
+	for i := 0; i < n; i++ {
+		r := optab[i].as
+		r0 := r & obj.AMask
+		oprange[r0].start = optab[i:]
+		for optab[i].as == r {
+			i++
+		}
+		oprange[r0].stop = optab[i:]
+		i--
+
+		switch r {
+		default:
+			ctxt.Diag("unknown op in build: %v", obj.Aconv(int(r)))
+			log.Fatalf("bad code")
+
+		case ADCBF: /* unary indexed: op (b+a); op (b) */
+			opset(ADCBI, r0)
+
+			opset(ADCBST, r0)
+			opset(ADCBT, r0)
+			opset(ADCBTST, r0)
+			opset(ADCBZ, r0)
+			opset(AICBI, r0)
+
+		case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
+			opset(ASTWCCC, r0)
+
+			opset(ASTDCCC, r0)
+
+		case AREM: /* macro */
+			opset(AREMCC, r0)
+
+			opset(AREMV, r0)
+			opset(AREMVCC, r0)
+
+		case AREMU:
+			opset(AREMU, r0)
+			opset(AREMUCC, r0)
+			opset(AREMUV, r0)
+			opset(AREMUVCC, r0)
+
+		case AREMD:
+			opset(AREMDCC, r0)
+			opset(AREMDV, r0)
+			opset(AREMDVCC, r0)
+
+		case AREMDU:
+			opset(AREMDU, r0)
+			opset(AREMDUCC, r0)
+			opset(AREMDUV, r0)
+			opset(AREMDUVCC, r0)
+
+		case ADIVW: /* op Rb[,Ra],Rd */
+			opset(AMULHW, r0)
+
+			opset(AMULHWCC, r0)
+			opset(AMULHWU, r0)
+			opset(AMULHWUCC, r0)
+			opset(AMULLWCC, r0)
+			opset(AMULLWVCC, r0)
+			opset(AMULLWV, r0)
+			opset(ADIVWCC, r0)
+			opset(ADIVWV, r0)
+			opset(ADIVWVCC, r0)
+			opset(ADIVWU, r0)
+			opset(ADIVWUCC, r0)
+			opset(ADIVWUV, r0)
+			opset(ADIVWUVCC, r0)
+			opset(AADDCC, r0)
+			opset(AADDCV, r0)
+			opset(AADDCVCC, r0)
+			opset(AADDV, r0)
+			opset(AADDVCC, r0)
+			opset(AADDE, r0)
+			opset(AADDECC, r0)
+			opset(AADDEV, r0)
+			opset(AADDEVCC, r0)
+			opset(ACRAND, r0)
+			opset(ACRANDN, r0)
+			opset(ACREQV, r0)
+			opset(ACRNAND, r0)
+			opset(ACRNOR, r0)
+			opset(ACROR, r0)
+			opset(ACRORN, r0)
+			opset(ACRXOR, r0)
+			opset(AMULHD, r0)
+			opset(AMULHDCC, r0)
+			opset(AMULHDU, r0)
+			opset(AMULHDUCC, r0)
+			opset(AMULLD, r0)
+			opset(AMULLDCC, r0)
+			opset(AMULLDVCC, r0)
+			opset(AMULLDV, r0)
+			opset(ADIVD, r0)
+			opset(ADIVDCC, r0)
+			opset(ADIVDVCC, r0)
+			opset(ADIVDV, r0)
+			opset(ADIVDU, r0)
+			opset(ADIVDUCC, r0)
+			opset(ADIVDUVCC, r0)
+			opset(ADIVDUCC, r0)
+
+		case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
+			opset(AMOVH, r0)
+
+			opset(AMOVHZ, r0)
+
+		case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
+			opset(AMOVHU, r0)
+
+			opset(AMOVHZU, r0)
+			opset(AMOVWU, r0)
+			opset(AMOVWZU, r0)
+			opset(AMOVDU, r0)
+			opset(AMOVMW, r0)
+
+		case AAND: /* logical op Rb,Rs,Ra; no literal */
+			opset(AANDN, r0)
+
+			opset(AANDNCC, r0)
+			opset(AEQV, r0)
+			opset(AEQVCC, r0)
+			opset(ANAND, r0)
+			opset(ANANDCC, r0)
+			opset(ANOR, r0)
+			opset(ANORCC, r0)
+			opset(AORCC, r0)
+			opset(AORN, r0)
+			opset(AORNCC, r0)
+			opset(AXORCC, r0)
+
+		case AADDME: /* op Ra, Rd */
+			opset(AADDMECC, r0)
+
+			opset(AADDMEV, r0)
+			opset(AADDMEVCC, r0)
+			opset(AADDZE, r0)
+			opset(AADDZECC, r0)
+			opset(AADDZEV, r0)
+			opset(AADDZEVCC, r0)
+			opset(ASUBME, r0)
+			opset(ASUBMECC, r0)
+			opset(ASUBMEV, r0)
+			opset(ASUBMEVCC, r0)
+			opset(ASUBZE, r0)
+			opset(ASUBZECC, r0)
+			opset(ASUBZEV, r0)
+			opset(ASUBZEVCC, r0)
+
+		case AADDC:
+			opset(AADDCCC, r0)
+
+		case ABEQ:
+			opset(ABGE, r0)
+			opset(ABGT, r0)
+			opset(ABLE, r0)
+			opset(ABLT, r0)
+			opset(ABNE, r0)
+			opset(ABVC, r0)
+			opset(ABVS, r0)
+
+		case ABR:
+			opset(ABL, r0)
+
+		case ABC:
+			opset(ABCL, r0)
+
+		case AEXTSB: /* op Rs, Ra */
+			opset(AEXTSBCC, r0)
+
+			opset(AEXTSH, r0)
+			opset(AEXTSHCC, r0)
+			opset(ACNTLZW, r0)
+			opset(ACNTLZWCC, r0)
+			opset(ACNTLZD, r0)
+			opset(AEXTSW, r0)
+			opset(AEXTSWCC, r0)
+			opset(ACNTLZDCC, r0)
+
+		case AFABS: /* fop [s,]d */
+			opset(AFABSCC, r0)
+
+			opset(AFNABS, r0)
+			opset(AFNABSCC, r0)
+			opset(AFNEG, r0)
+			opset(AFNEGCC, r0)
+			opset(AFRSP, r0)
+			opset(AFRSPCC, r0)
+			opset(AFCTIW, r0)
+			opset(AFCTIWCC, r0)
+			opset(AFCTIWZ, r0)
+			opset(AFCTIWZCC, r0)
+			opset(AFCTID, r0)
+			opset(AFCTIDCC, r0)
+			opset(AFCTIDZ, r0)
+			opset(AFCTIDZCC, r0)
+			opset(AFCFID, r0)
+			opset(AFCFIDCC, r0)
+			opset(AFRES, r0)
+			opset(AFRESCC, r0)
+			opset(AFRSQRTE, r0)
+			opset(AFRSQRTECC, r0)
+			opset(AFSQRT, r0)
+			opset(AFSQRTCC, r0)
+			opset(AFSQRTS, r0)
+			opset(AFSQRTSCC, r0)
+
+		case AFADD:
+			opset(AFADDS, r0)
+			opset(AFADDCC, r0)
+			opset(AFADDSCC, r0)
+			opset(AFDIV, r0)
+			opset(AFDIVS, r0)
+			opset(AFDIVCC, r0)
+			opset(AFDIVSCC, r0)
+			opset(AFSUB, r0)
+			opset(AFSUBS, r0)
+			opset(AFSUBCC, r0)
+			opset(AFSUBSCC, r0)
+
+		case AFMADD:
+			opset(AFMADDCC, r0)
+			opset(AFMADDS, r0)
+			opset(AFMADDSCC, r0)
+			opset(AFMSUB, r0)
+			opset(AFMSUBCC, r0)
+			opset(AFMSUBS, r0)
+			opset(AFMSUBSCC, r0)
+			opset(AFNMADD, r0)
+			opset(AFNMADDCC, r0)
+			opset(AFNMADDS, r0)
+			opset(AFNMADDSCC, r0)
+			opset(AFNMSUB, r0)
+			opset(AFNMSUBCC, r0)
+			opset(AFNMSUBS, r0)
+			opset(AFNMSUBSCC, r0)
+			opset(AFSEL, r0)
+			opset(AFSELCC, r0)
+
+		case AFMUL:
+			opset(AFMULS, r0)
+			opset(AFMULCC, r0)
+			opset(AFMULSCC, r0)
+
+		case AFCMPO:
+			opset(AFCMPU, r0)
+
+		case AMTFSB0:
+			opset(AMTFSB0CC, r0)
+			opset(AMTFSB1, r0)
+			opset(AMTFSB1CC, r0)
+
+		case ANEG: /* op [Ra,] Rd */
+			opset(ANEGCC, r0)
+
+			opset(ANEGV, r0)
+			opset(ANEGVCC, r0)
+
+		case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
+			opset(AXOR, r0)
+
+		case ASLW:
+			opset(ASLWCC, r0)
+			opset(ASRW, r0)
+			opset(ASRWCC, r0)
+
+		case ASLD:
+			opset(ASLDCC, r0)
+			opset(ASRD, r0)
+			opset(ASRDCC, r0)
+
+		case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+			opset(ASRAWCC, r0)
+
+		case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+			opset(ASRADCC, r0)
+
+		case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
+			opset(ASUB, r0)
+
+			opset(ASUBCC, r0)
+			opset(ASUBV, r0)
+			opset(ASUBVCC, r0)
+			opset(ASUBCCC, r0)
+			opset(ASUBCV, r0)
+			opset(ASUBCVCC, r0)
+			opset(ASUBE, r0)
+			opset(ASUBECC, r0)
+			opset(ASUBEV, r0)
+			opset(ASUBEVCC, r0)
+
+		case ASYNC:
+			opset(AISYNC, r0)
+			opset(APTESYNC, r0)
+			opset(ATLBSYNC, r0)
+
+		case ARLWMI:
+			opset(ARLWMICC, r0)
+			opset(ARLWNM, r0)
+			opset(ARLWNMCC, r0)
+
+		case ARLDMI:
+			opset(ARLDMICC, r0)
+
+		case ARLDC:
+			opset(ARLDCCC, r0)
+
+		case ARLDCL:
+			opset(ARLDCR, r0)
+			opset(ARLDCLCC, r0)
+			opset(ARLDCRCC, r0)
+
+		case AFMOVD:
+			opset(AFMOVDCC, r0)
+			opset(AFMOVDU, r0)
+			opset(AFMOVS, r0)
+			opset(AFMOVSU, r0)
+
+		case AECIWX:
+			opset(ALWAR, r0)
+			opset(ALDAR, r0)
+
+		case ASYSCALL: /* just the op; flow of control */
+			opset(ARFI, r0)
+
+			opset(ARFCI, r0)
+			opset(ARFID, r0)
+			opset(AHRFID, r0)
+
+		case AMOVHBR:
+			opset(AMOVWBR, r0)
+
+		case ASLBMFEE:
+			opset(ASLBMFEV, r0)
+
+		case ATW:
+			opset(ATD, r0)
+
+		case ATLBIE:
+			opset(ASLBIE, r0)
+			opset(ATLBIEL, r0)
+
+		case AEIEIO:
+			opset(ASLBIA, r0)
+
+		case ACMP:
+			opset(ACMPW, r0)
+
+		case ACMPU:
+			opset(ACMPWU, r0)
+
+		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,
+			obj.ANOP,
+			obj.ATEXT,
+			obj.AUNDEF,
+			obj.AUSEFIELD,
+			obj.AFUNCDATA,
+			obj.APCDATA,
+			obj.ADUFFZERO,
+			obj.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 (
+	/* each rhs is OPVCC(_, _, _, _) */
+	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) {
+	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) bool {
+	m[1] = 0
+	m[0] = m[1]
+	if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
+		if getmask(m, ^v) {
+			i := int(m[0])
+			m[0] = m[1] + 1
+			m[1] = byte(i - 1)
+			return true
+		}
+
+		return false
+	}
+
+	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 false
+				}
+			}
+			return true
+		}
+	}
+
+	return false
+}
+
+func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
+	if !getmask(m, v) {
+		ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+	}
+}
+
+/*
+ * 64-bit masks (rldic etc)
+ */
+func getmask64(m []byte, v uint64) bool {
+	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 false
+				}
+			}
+			return true
+		}
+	}
+
+	return false
+}
+
+func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
+	if !getmask64(m, v) {
+		ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+	}
+}
+
+func loadu32(r int, d int64) uint32 {
+	v := int32(d >> 16)
+	if isuint32(uint64(d)) {
+		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) {
+	o1 := uint32(0)
+	o2 := uint32(0)
+	o3 := uint32(0)
+	o4 := uint32(0)
+	o5 := uint32(0)
+
+	//print("%v => 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 == obj.TYPE_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 == 0 {
+			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 == 0 {
+			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)) {
+				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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			r = int(o.param)
+		}
+		v := regoff(ctxt, &p.To)
+		if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 {
+			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.To.Index), 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 == 0 {
+			r = int(o.param)
+		}
+		v := regoff(ctxt, &p.From)
+		if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
+			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.From.Index), 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 == 0 {
+			r = int(o.param)
+		}
+		v := regoff(ctxt, &p.From)
+		if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
+			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.From.Index), 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 == 0 {
+			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 := int32(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 == obj.TYPE_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 == 0 {
+			r = int(p.To.Reg)
+		}
+		d := vregoff(ctxt, p.From3)
+		var mask [2]uint8
+		maskgen64(ctxt, p, mask[:], uint64(d))
+		var a int
+		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 == obj.TYPE_CONST {
+			a = int(regoff(ctxt, &p.From))
+		}
+		r := int(p.Reg)
+		if r == 0 {
+			r = 0
+		}
+		v := int32(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) */
+		var v int32
+		if p.As == ABC || p.As == ABCL {
+			v = regoff(ctxt, &p.To) & 31
+		} else {
+			v = 20 /* unconditional */
+		}
+		o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (REG_LR&0x1f)<<16 | ((REG_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(p.To.Index))
+
+	case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
+		var v int32
+		if p.As == ABC || p.As == ABCL {
+			v = regoff(ctxt, &p.From) & 31
+		} else {
+			v = 20 /* unconditional */
+		}
+		r := int(p.Reg)
+		if r == 0 {
+			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 == 0 {
+			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)+ALAST)), 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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			r = int(p.To.Reg)
+		}
+		var a int
+		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 == 0 {
+			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)
+		var mask [2]uint8
+		maskgen64(ctxt, p, mask[:], uint64(d))
+		var a int
+		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)
+		var mask [2]uint8
+		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.ByteOrder == binary.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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			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) */
+		o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(p.From.Index), uint32(p.From.Reg))
+
+	case 44: /* indexed store */
+		o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(p.To.Reg))
+
+	case 45: /* indexed load */
+		o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), 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 == 0 {
+			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 == 0 {
+			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 != obj.TYPE_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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			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 == 0 {
+			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%v", v, p);
+		*/
+		if v < 0 {
+			v = 0
+		} else if v > 32 {
+			v = 32
+		}
+		var mask [2]uint8
+		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 == 0 {
+			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 == 0 {
+			r = int(p.To.Reg)
+		}
+		o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), 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)
+
+		var mask [2]uint8
+		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 */
+		var mask [2]uint8
+		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} */
+		var v int32
+		if p.From3Type() != obj.TYPE_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 == 0 {
+			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 */
+		var r int
+		var v int32
+		if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 {
+			r = int(p.From.Reg)
+			v = int32(p.To.Reg)
+			if REG_DCR0 <= v && v <= REG_DCR0+1023 {
+				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.Reg)
+			if REG_DCR0 <= v && v <= REG_DCR0+1023 {
+				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 != obj.TYPE_REG || p.From.Reg < REG_CR0 || REG_CR7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
+			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 == obj.TYPE_REG && REG_CR0 <= p.From.Reg && p.From.Reg <= REG_CR7 {
+			v := int32(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 */
+		var v int32
+		if p.From3Type() != obj.TYPE_NONE {
+			if p.To.Reg != 0 {
+				ctxt.Diag("can't use both mask and CR(n)\n%v", p)
+			}
+			v = regoff(ctxt, p.From3) & 0xff
+		} else {
+			if p.To.Reg == 0 {
+				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*/
+		var r int
+		if p.Reg == 0 {
+			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*/
+		var r int
+		if p.Reg == 0 {
+			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 != obj.TYPE_REG || p.From.Reg != REG_FPSCR || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg {
+			ctxt.Diag("illegal FPSCR/CR field number\n%v", p)
+		}
+		o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0)
+
+	case 77: /* syscall $scon, syscall Rx */
+		if p.From.Type == obj.TYPE_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 == obj.TYPE_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);
+
+	}
+
+	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
+	if a != nil {
+		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", obj.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 + ALAST:
+		return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */
+
+	case AANDCC:
+		return int32(OPVCC(28, 0, 0, 0))
+	case AANDCC + ALAST:
+		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 obj.ADUFFZERO:
+		return int32(OPVCC(18, 0, 0, 0) | 1)
+	case obj.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 + ALAST:
+		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 + ALAST:
+		return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
+	}
+
+	ctxt.Diag("bad opcode i/r %v", obj.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", obj.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", obj.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", obj.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", obj.Aconv(a))
+	return 0
+}
diff --git a/src/cmd/internal/obj/mips/list0.go b/src/cmd/internal/obj/mips/list0.go
new file mode 100644
index 0000000..4cdcfbc
--- /dev/null
+++ b/src/cmd/internal/obj/mips/list0.go
@@ -0,0 +1,98 @@
+// 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"
+)
+
+func init() {
+	obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, Rconv)
+	obj.RegisterOpcode(obj.ABasePPC64, Anames)
+}
+
+func Rconv(r int) string {
+	if r == 0 {
+		return "NONE"
+	}
+	if r == REGG {
+		// Special case.
+		return "g"
+	}
+	if REG_R0 <= r && r <= REG_R31 {
+		return fmt.Sprintf("R%d", r-REG_R0)
+	}
+	if REG_F0 <= r && r <= REG_F31 {
+		return fmt.Sprintf("F%d", r-REG_F0)
+	}
+	if REG_CR0 <= r && r <= REG_CR7 {
+		return fmt.Sprintf("CR%d", r-REG_CR0)
+	}
+	if r == REG_CR {
+		return "CR"
+	}
+	if REG_SPR0 <= r && r <= REG_SPR0+1023 {
+		switch r {
+		case REG_XER:
+			return "XER"
+
+		case REG_LR:
+			return "LR"
+
+		case REG_CTR:
+			return "CTR"
+		}
+
+		return fmt.Sprintf("SPR(%d)", r-REG_SPR0)
+	}
+
+	if REG_DCR0 <= r && r <= REG_DCR0+1023 {
+		return fmt.Sprintf("DCR(%d)", r-REG_DCR0)
+	}
+	if r == REG_FPSCR {
+		return "FPSCR"
+	}
+	if r == REG_MSR {
+		return "MSR"
+	}
+
+	return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64)
+}
+
+func DRconv(a int) string {
+	s := "C_??"
+	if a >= C_NONE && a <= C_NCLASS {
+		s = cnames9[a]
+	}
+	var fp string
+	fp += s
+	return fp
+}
diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go
new file mode 100644
index 0000000..1eddc6f
--- /dev/null
+++ b/src/cmd/internal/obj/mips/obj0.go
@@ -0,0 +1,968 @@
+// 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"
+)
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+	p.From.Class = 0
+	p.To.Class = 0
+
+	// Rewrite BR/BL to symbol as TYPE_BRANCH.
+	switch p.As {
+	case ABR,
+		ABL,
+		obj.ARET,
+		obj.ADUFFZERO,
+		obj.ADUFFCOPY:
+		if p.To.Sym != nil {
+			p.To.Type = obj.TYPE_BRANCH
+		}
+	}
+
+	// Rewrite float constants to values stored in memory.
+	switch p.As {
+	case AFMOVS:
+		if p.From.Type == obj.TYPE_FCONST {
+			f32 := float32(p.From.Val.(float64))
+			i32 := math.Float32bits(f32)
+			literal := fmt.Sprintf("$f32.%08x", i32)
+			s := obj.Linklookup(ctxt, literal, 0)
+			s.Size = 4
+			p.From.Type = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+
+	case AFMOVD:
+		if p.From.Type == obj.TYPE_FCONST {
+			i64 := math.Float64bits(p.From.Val.(float64))
+			literal := fmt.Sprintf("$f64.%016x", i64)
+			s := obj.Linklookup(ctxt, literal, 0)
+			s.Size = 8
+			p.From.Type = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+
+		// Put >32-bit constants in memory and load them
+	case AMOVD:
+		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && 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 = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+	}
+
+	// Rewrite SUB constants into ADD.
+	switch p.As {
+	case ASUBC:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADDC
+		}
+
+	case ASUBCCC:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADDCCC
+		}
+
+	case ASUB:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADD
+		}
+	}
+}
+
+func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
+	// 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
+	textstksiz := p.To.Offset
+
+	cursym.Args = p.To.Val.(int32)
+	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())
+	}
+	ctxt.Bso.Flush()
+
+	var q *obj.Prog
+	var q1 *obj.Prog
+	for p := cursym.Text; p != nil; p = p.Link {
+		switch p.As {
+		/* too hard, just leave alone */
+		case obj.ATEXT:
+			q = p
+
+			p.Mark |= LABEL | LEAF | SYNC
+			if p.Link != nil {
+				p.Link.Mark |= LABEL
+			}
+
+		case ANOR:
+			q = p
+			if p.To.Type == obj.TYPE_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
+			if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
+				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,
+			obj.ADUFFZERO,
+			obj.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 == obj.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 obj.ARET:
+			q = p
+			if p.Link != nil {
+				p.Link.Mark |= LABEL
+			}
+			continue
+
+		case obj.ANOP:
+			q1 = p.Link
+			q.Link = q1 /* q is non-nop */
+			q1.Mark |= p.Mark
+			continue
+
+		default:
+			q = p
+			continue
+		}
+	}
+
+	autosize := int32(0)
+	var aoffset int
+	var mov int
+	var o int
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+	for p := cursym.Text; p != nil; p = p.Link {
+		o = int(p.As)
+		switch o {
+		case obj.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(autosize) - 8
+
+			if p.From3.Offset&obj.NOSPLIT == 0 {
+				p = stacksplit(ctxt, p, autosize) // 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 = obj.TYPE_CONST
+					q.From.Offset = int64(-autosize)
+					q.To.Type = obj.TYPE_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)
+					ctxt.Bso.Flush()
+				}
+
+				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 = obj.TYPE_REG
+			q.From.Reg = REG_LR
+			q.To.Type = obj.TYPE_REG
+			q.To.Reg = REGTMP
+
+			q = obj.Appendp(ctxt, q)
+			q.As = int16(mov)
+			q.Lineno = p.Lineno
+			q.From.Type = obj.TYPE_REG
+			q.From.Reg = REGTMP
+			q.To.Type = obj.TYPE_MEM
+			q.To.Offset = int64(aoffset)
+			q.To.Reg = REGSP
+			if q.As == AMOVDU {
+				q.Spadj = int32(-aoffset)
+			}
+
+			if cursym.Text.From3.Offset&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 = obj.TYPE_MEM
+				q.From.Reg = REGG
+				q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R3
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ACMP
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R0
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R3
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ABEQ
+				q.To.Type = obj.TYPE_BRANCH
+				p1 = q
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AMOVD
+				q.From.Type = obj.TYPE_MEM
+				q.From.Reg = REG_R3
+				q.From.Offset = 0 // Panic.argp
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R4
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AADD
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = int64(autosize) + 8
+				q.Reg = REGSP
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R5
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ACMP
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R4
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R5
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ABNE
+				q.To.Type = obj.TYPE_BRANCH
+				p2 = q
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AADD
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = 8
+				q.Reg = REGSP
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R6
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AMOVD
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R6
+				q.To.Type = obj.TYPE_MEM
+				q.To.Reg = REG_R3
+				q.To.Offset = 0 // Panic.argp
+
+				q = obj.Appendp(ctxt, q)
+
+				q.As = obj.ANOP
+				p1.Pcond = q
+				p2.Pcond = q
+			}
+
+		case obj.ARET:
+			if p.From.Type == obj.TYPE_CONST {
+				ctxt.Diag("using BECOME (%v) is not supported!", p)
+				break
+			}
+
+			if p.To.Sym != nil { // retjmp
+				p.As = ABR
+				p.To.Type = obj.TYPE_BRANCH
+				break
+			}
+
+			if cursym.Text.Mark&LEAF != 0 {
+				if autosize == 0 {
+					p.As = ABR
+					p.From = obj.Addr{}
+					p.To.Type = obj.TYPE_REG
+					p.To.Reg = REG_LR
+					p.Mark |= BRANCH
+					break
+				}
+
+				p.As = AADD
+				p.From.Type = obj.TYPE_CONST
+				p.From.Offset = int64(autosize)
+				p.To.Type = obj.TYPE_REG
+				p.To.Reg = REGSP
+				p.Spadj = -autosize
+
+				q = ctxt.NewProg()
+				q.As = ABR
+				q.Lineno = p.Lineno
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_LR
+				q.Mark |= BRANCH
+				q.Spadj = +autosize
+
+				q.Link = p.Link
+				p.Link = q
+				break
+			}
+
+			p.As = AMOVD
+			p.From.Type = obj.TYPE_MEM
+			p.From.Offset = 0
+			p.From.Reg = REGSP
+			p.To.Type = obj.TYPE_REG
+			p.To.Reg = REGTMP
+
+			q = ctxt.NewProg()
+			q.As = AMOVD
+			q.Lineno = p.Lineno
+			q.From.Type = obj.TYPE_REG
+			q.From.Reg = REGTMP
+			q.To.Type = obj.TYPE_REG
+			q.To.Reg = REG_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 = obj.TYPE_MEM
+				q.From.Offset = 0
+				q.From.Reg = REGTMP
+				q.To.Type = obj.TYPE_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 = obj.TYPE_CONST
+				q.From.Offset = int64(autosize)
+				q.To.Type = obj.TYPE_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 = obj.TYPE_REG
+			q1.To.Reg = REG_LR
+			q1.Mark |= BRANCH
+			q1.Spadj = +autosize
+
+			q1.Link = q.Link
+			q.Link = q1
+
+		case AADD:
+			if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
+				p.Spadj = int32(-p.From.Offset)
+			}
+		}
+	}
+}
+
+/*
+// 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) *obj.Prog {
+	// MOVD	g_stackguard(g), R3
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AMOVD
+	p.From.Type = obj.TYPE_MEM
+	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 = obj.TYPE_REG
+	p.To.Reg = REG_R3
+
+	var q *obj.Prog
+	if framesize <= obj.StackSmall {
+		// small stack: SP < stackguard
+		//	CMP	stackguard, SP
+		p = obj.Appendp(ctxt, p)
+
+		p.As = ACMPU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R3
+		p.To.Type = obj.TYPE_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 = obj.TYPE_CONST
+		p.From.Offset = int64(-framesize)
+		p.Reg = REGSP
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R4
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ACMPU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R3
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R4
+	} 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 = obj.TYPE_REG
+		p.From.Reg = REG_R3
+		p.To.Type = obj.TYPE_CONST
+		p.To.Offset = obj.StackPreempt
+
+		p = obj.Appendp(ctxt, p)
+		q = p
+		p.As = ABEQ
+		p.To.Type = obj.TYPE_BRANCH
+
+		p = obj.Appendp(ctxt, p)
+		p.As = AADD
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = obj.StackGuard
+		p.Reg = REGSP
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R4
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ASUB
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R3
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R4
+
+		p = obj.Appendp(ctxt, p)
+		p.As = AMOVD
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REGTMP
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ACMPU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REGTMP
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R4
+	}
+
+	// q1: BLT	done
+	p = obj.Appendp(ctxt, p)
+	q1 := p
+
+	p.As = ABLT
+	p.To.Type = obj.TYPE_BRANCH
+
+	// MOVD	LR, R5
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AMOVD
+	p.From.Type = obj.TYPE_REG
+	p.From.Reg = REG_LR
+	p.To.Type = obj.TYPE_REG
+	p.To.Reg = REG_R5
+	if q != nil {
+		q.Pcond = p
+	}
+
+	// BL	runtime.morestack(SB)
+	p = obj.Appendp(ctxt, p)
+
+	p.As = ABL
+	p.To.Type = obj.TYPE_BRANCH
+	if ctxt.Cursym.Cfunc != 0 {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+	} else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+	} else {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
+	}
+
+	// BR	start
+	p = obj.Appendp(ctxt, p)
+
+	p.As = ABR
+	p.To.Type = obj.TYPE_BRANCH
+	p.Pcond = ctxt.Cursym.Text.Link
+
+	// placeholder for q1's jump target
+	p = obj.Appendp(ctxt, p)
+
+	p.As = obj.ANOP // zero-width place holder
+	q1.Pcond = p
+
+	return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+	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; i, q = i+1, q.Link {
+			if q == *last || (q.Mark&NOSCHED != 0) {
+				break
+			}
+			b = 0 /* set */
+			a = int(q.As)
+			if a == obj.ANOP {
+				i--
+				continue
+			}
+
+			if a == ABR || a == obj.ARET || 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 == obj.ARET || 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 = obj.TYPE_BRANCH
+		q.To.Offset = p.Pc
+		q.Pcond = p
+		p = q
+	}
+
+	p.Mark |= FOLL
+	(*last).Link = p
+	*last = p
+	if a == ABR || a == obj.ARET || 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
+}
+
+var Linkppc64 = obj.LinkArch{
+	ByteOrder:  binary.BigEndian,
+	Name:       "ppc64",
+	Thechar:    '9',
+	Preprocess: preprocess,
+	Assemble:   span9,
+	Follow:     follow,
+	Progedit:   progedit,
+	Minlc:      4,
+	Ptrsize:    8,
+	Regsize:    8,
+}
+
+var Linkppc64le = obj.LinkArch{
+	ByteOrder:  binary.LittleEndian,
+	Name:       "ppc64le",
+	Thechar:    '9',
+	Preprocess: preprocess,
+	Assemble:   span9,
+	Follow:     follow,
+	Progedit:   progedit,
+	Minlc:      4,
+	Ptrsize:    8,
+	Regsize:    8,
+}