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,
+}