aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/mips
diff options
context:
space:
mode:
authorYao Zhang <lunaria21@gmail.com>2015-09-10 11:13:00 -0400
committerMinux Ma <minux@golang.org>2015-11-12 04:42:44 +0000
commitfa6a1ecd6327ffbedc7dd117e0fba819f6f4faf1 (patch)
tree23f170aca2eac99230d8ab5c594831430056e099 /src/cmd/internal/obj/mips
parenta9bebd91c986b3bcd96fae02e54357365b0097d2 (diff)
downloadgo-fa6a1ecd6327ffbedc7dd117e0fba819f6f4faf1.tar.xz
cmd/internal/obj/mips: added support for GOARCH=mips64{,le}
MIPS64 has 32 general purpose 64-bit integer registers (R0-R31), 32 64-bit floating point registers (F0-F31). Instructions are fixed-width, and are 32-bit wide. Instructions are all in standard 1-, 2-, 3-operand forms. MIPS64-specific relocations are added. For this reason, test data of cmd/newlink are regenerated. No other changes are made to portable structures. Branch delay slots are current filled with NOP instructions. The function for instruction scheduling (try to fill the delay slot with a useful instruction) is implemented but disabled for now. Change-Id: Ic364999c7a33245260c1381fc26a2fa8972d38b3 Reviewed-on: https://go-review.googlesource.com/14442 Reviewed-by: Minux Ma <minux@golang.org>
Diffstat (limited to 'src/cmd/internal/obj/mips')
-rw-r--r--src/cmd/internal/obj/mips/a.out.go552
-rw-r--r--src/cmd/internal/obj/mips/anames.go364
-rw-r--r--src/cmd/internal/obj/mips/anames0.go18
-rw-r--r--src/cmd/internal/obj/mips/asm0.go3385
-rw-r--r--src/cmd/internal/obj/mips/list0.go44
-rw-r--r--src/cmd/internal/obj/mips/obj0.go1215
6 files changed, 2112 insertions, 3466 deletions
diff --git a/src/cmd/internal/obj/mips/a.out.go b/src/cmd/internal/obj/mips/a.out.go
index 3028b6cac8..f271a87609 100644
--- a/src/cmd/internal/obj/mips/a.out.go
+++ b/src/cmd/internal/obj/mips/a.out.go
@@ -27,14 +27,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import "cmd/internal/obj"
-//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p ppc64
+//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p mips
/*
- * powerpc 64
+ * mips 64
*/
const (
NSNAME = 8
@@ -44,7 +44,7 @@ const (
)
const (
- REG_R0 = obj.RBasePPC64 + iota
+ REG_R0 = obj.RBaseMIPS64 + iota
REG_R1
REG_R2
REG_R3
@@ -110,90 +110,128 @@ const (
REG_F30
REG_F31
- REG_CR0
- REG_CR1
- REG_CR2
- REG_CR3
- REG_CR4
- REG_CR5
- REG_CR6
- REG_CR7
+ REG_HI
+ REG_LO
- REG_MSR
- REG_FPSCR
- REG_CR
+ // co-processor 0 control registers
+ REG_M0 = obj.RBaseMIPS64 + 1024 + iota
+ REG_M1
+ REG_M2
+ REG_M3
+ REG_M4
+ REG_M5
+ REG_M6
+ REG_M7
+ REG_M8
+ REG_M9
+ REG_M10
+ REG_M11
+ REG_M12
+ REG_M13
+ REG_M14
+ REG_M15
+ REG_M16
+ REG_M17
+ REG_M18
+ REG_M19
+ REG_M20
+ REG_M21
+ REG_M22
+ REG_M23
+ REG_M24
+ REG_M25
+ REG_M26
+ REG_M27
+ REG_M28
+ REG_M29
+ REG_M30
+ REG_M31
- REG_SPECIAL = REG_CR0
+ // FPU control registers
+ REG_FCR0 = obj.RBaseMIPS64 + 2048 + iota
+ REG_FCR1
+ REG_FCR2
+ REG_FCR3
+ REG_FCR4
+ REG_FCR5
+ REG_FCR6
+ REG_FCR7
+ REG_FCR8
+ REG_FCR9
+ REG_FCR10
+ REG_FCR11
+ REG_FCR12
+ REG_FCR13
+ REG_FCR14
+ REG_FCR15
+ REG_FCR16
+ REG_FCR17
+ REG_FCR18
+ REG_FCR19
+ REG_FCR20
+ REG_FCR21
+ REG_FCR22
+ REG_FCR23
+ REG_FCR24
+ REG_FCR25
+ REG_FCR26
+ REG_FCR27
+ REG_FCR28
+ REG_FCR29
+ REG_FCR30
+ REG_FCR31
- 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
+ REG_SPECIAL = REG_M0
REGZERO = REG_R0 /* set to zero */
- REGSP = REG_R1
- REGSB = REG_R2
- REGRET = REG_R3
+ REGSP = REG_R29
+ REGSB = REG_R30
+ REGLINK = REG_R31
+ REGRET = REG_R1
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 */
+ REGRT1 = REG_R1 /* reserved for runtime, duffzero and duffcopy */
+ REGRT2 = REG_R2 /* reserved for runtime, duffcopy */
+ REGCTXT = REG_R22 /* context for closures */
REGG = REG_R30 /* G */
- REGTMP = REG_R31 /* used by the linker */
+ REGTMP = REG_R28 /* 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 */
+ FREGZERO = REG_F24 /* both float and double */
+ FREGHALF = REG_F26 /* double */
+ FREGONE = REG_F28 /* double */
+ FREGTWO = REG_F30 /* 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
+ BIG = 32766
)
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
+ FOLL = 1 << 0
+ LABEL = 1 << 1
+ LEAF = 1 << 2
+ SYNC = 1 << 3
+ BRANCH = 1 << 4
+ LOAD = 1 << 5
+ FCMP = 1 << 6
+ NOSCHED = 1 << 7
+
+ NSCHED = 20
)
const (
C_NONE = iota
C_REG
C_FREG
- C_CREG
- C_SPR /* special processor register */
+ C_FCREG
+ C_MREG /* special processor register */
+ C_HI
+ C_LO
C_ZCON
- C_SCON /* 16 bit signed */
- C_UCON /* 32 bit signed, low 16 bits 0 */
+ C_SCON /* 16 bit signed */
+ C_UCON /* 32 bit signed, low 16 bits 0 */
+ C_ADD0CON
+ C_AND0CON
C_ADDCON /* -0x8000 <= v < 0 */
C_ANDCON /* 0 < v <= 0xFFFF */
C_LCON /* other 32 */
@@ -212,12 +250,6 @@ const (
C_ZOREG
C_SOREG
C_LOREG
- C_FPSCR
- C_MSR
- C_XER
- C_LR
- C_CTR
- C_ANY
C_GOK
C_ADDR
C_TEXTSIZE
@@ -226,313 +258,117 @@ const (
)
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
+ AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota
+ AABSF
+ AABSW
+ AADD
+ AADDD
+ AADDF
+ AADDU
+ AADDW
AAND
- AANDCC
- AANDN
- AANDNCC
- ABC
- ABCL
ABEQ
- ABGE
- ABGT
- ABLE
- ABLT
+ ABFPF
+ ABFPT
+ ABGEZ
+ ABGEZAL
+ ABGTZ
+ ABLEZ
+ ABLTZ
+ ABLTZAL
ABNE
- ABVC
- ABVS
- ACMP
- ACMPU
- ACNTLZW
- ACNTLZWCC
- ACRAND
- ACRANDN
- ACREQV
- ACRNAND
- ACRNOR
- ACROR
- ACRORN
- ACRXOR
+ ABREAK
+ ACMPEQD
+ ACMPEQF
+ ACMPGED
+ ACMPGEF
+ ACMPGTD
+ ACMPGTF
+ ADIV
+ ADIVD
+ ADIVF
+ ADIVU
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
+ AGOK
AMOVB
AMOVBU
- AMOVBZ
- AMOVBZU
+ AMOVD
+ AMOVDF
+ AMOVDW
+ AMOVF
+ AMOVFD
+ AMOVFW
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
+ AMOVWD
+ AMOVWF
+ AMOVWL
+ AMOVWR
+ AMUL
+ AMULD
+ AMULF
+ AMULU
+ AMULW
+ ANEGD
+ ANEGF
+ ANEGW
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
+ ARFE
+ ASGT
+ ASGTU
+ ASLL
+ ASRA
+ ASRL
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
-
+ ASUBD
+ ASUBF
+ ASUBU
+ ASUBW
ASYSCALL
+ ATLBP
+ ATLBR
+ ATLBWI
+ ATLBWR
AWORD
-
- ARFCI
-
- /* optional on 32-bit */
- AFRES
- AFRESCC
- AFRSQRTE
- AFRSQRTECC
- AFSEL
- AFSELCC
- AFSQRT
- AFSQRTCC
- AFSQRTS
- AFSQRTSCC
+ AXOR
/* 64-bit */
+ AMOVV
+ AMOVVL
+ AMOVVR
+ ASLLV
+ ASRAV
+ ASRLV
+ ADIVV
+ ADIVVU
+ AREMV
+ AREMVU
+ AMULV
+ AMULVU
+ AADDV
+ AADDVU
+ ASUBV
+ ASUBVU
- 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
+ /* 64-bit FP */
+ ATRUNCFV
+ ATRUNCDV
+ ATRUNCFW
+ ATRUNCDW
+ AMOVWU
+ AMOVFV
+ AMOVDV
+ AMOVVF
+ AMOVVD
ALAST
// aliases
- ABR = obj.AJMP
- ABL = obj.ACALL
+ AJMP = obj.AJMP
+ AJAL = obj.ACALL
+ ARET = obj.ARET
)
diff --git a/src/cmd/internal/obj/mips/anames.go b/src/cmd/internal/obj/mips/anames.go
index 1ae7a52015..a943e503ac 100644
--- a/src/cmd/internal/obj/mips/anames.go
+++ b/src/cmd/internal/obj/mips/anames.go
@@ -1,300 +1,112 @@
-// Generated by stringer -i a.out.go -o anames.go -p ppc64
+// Generated by stringer -i a.out.go -o anames.go -p mips
// Do not edit.
-package ppc64
+package mips
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",
+ obj.A_ARCHSPECIFIC: "ABSD",
+ "ABSF",
+ "ABSW",
+ "ADD",
+ "ADDD",
+ "ADDF",
+ "ADDU",
+ "ADDW",
"AND",
- "ANDCC",
- "ANDN",
- "ANDNCC",
- "BC",
- "BCL",
"BEQ",
- "BGE",
- "BGT",
- "BLE",
- "BLT",
+ "BFPF",
+ "BFPT",
+ "BGEZ",
+ "BGEZAL",
+ "BGTZ",
+ "BLEZ",
+ "BLTZ",
+ "BLTZAL",
"BNE",
- "BVC",
- "BVS",
- "CMP",
- "CMPU",
- "CNTLZW",
- "CNTLZWCC",
- "CRAND",
- "CRANDN",
- "CREQV",
- "CRNAND",
- "CRNOR",
- "CROR",
- "CRORN",
- "CRXOR",
+ "BREAK",
+ "CMPEQD",
+ "CMPEQF",
+ "CMPGED",
+ "CMPGEF",
+ "CMPGTD",
+ "CMPGTF",
+ "DIV",
+ "DIVD",
+ "DIVF",
+ "DIVU",
"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",
+ "GOK",
"MOVB",
"MOVBU",
- "MOVBZ",
- "MOVBZU",
+ "MOVD",
+ "MOVDF",
+ "MOVDW",
+ "MOVF",
+ "MOVFD",
+ "MOVFW",
"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",
+ "MOVWD",
+ "MOVWF",
+ "MOVWL",
+ "MOVWR",
+ "MUL",
+ "MULD",
+ "MULF",
+ "MULU",
+ "MULW",
+ "NEGD",
+ "NEGF",
+ "NEGW",
"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",
+ "RFE",
+ "SGT",
+ "SGTU",
+ "SLL",
+ "SRA",
+ "SRL",
"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",
+ "SUBD",
+ "SUBF",
+ "SUBU",
+ "SUBW",
"SYSCALL",
+ "TLBP",
+ "TLBR",
+ "TLBWI",
+ "TLBWR",
"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",
+ "XOR",
+ "MOVV",
+ "MOVVL",
+ "MOVVR",
+ "SLLV",
+ "SRAV",
+ "SRLV",
+ "DIVV",
+ "DIVVU",
+ "REMV",
+ "REMVU",
+ "MULV",
+ "MULVU",
+ "ADDV",
+ "ADDVU",
+ "SUBV",
+ "SUBVU",
+ "TRUNCFV",
+ "TRUNCDV",
+ "TRUNCFW",
+ "TRUNCDW",
+ "MOVWU",
+ "MOVFV",
+ "MOVDV",
+ "MOVVF",
+ "MOVVD",
"LAST",
}
diff --git a/src/cmd/internal/obj/mips/anames0.go b/src/cmd/internal/obj/mips/anames0.go
index b48e5162b0..7f342e6895 100644
--- a/src/cmd/internal/obj/mips/anames0.go
+++ b/src/cmd/internal/obj/mips/anames0.go
@@ -1,14 +1,18 @@
-package ppc64
+package mips
-var cnames9 = []string{
+var cnames0 = []string{
"NONE",
"REG",
"FREG",
- "CREG",
- "SPR",
+ "FCREG",
+ "MREG",
+ "HI",
+ "LO",
"ZCON",
"SCON",
"UCON",
+ "ADD0CON",
+ "AND0CON",
"ADDCON",
"ANDCON",
"LCON",
@@ -27,12 +31,6 @@ var cnames9 = []string{
"ZOREG",
"SOREG",
"LOREG",
- "FPSCR",
- "MSR",
- "XER",
- "LR",
- "CTR",
- "ANY",
"GOK",
"ADDR",
"TEXTSIZE",
diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go
index c7498ea5f3..f944d3333f 100644
--- a/src/cmd/internal/obj/mips/asm0.go
+++ b/src/cmd/internal/obj/mips/asm0.go
@@ -27,11 +27,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
- "encoding/binary"
"fmt"
"log"
"sort"
@@ -52,349 +51,263 @@ type Optab struct {
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},
+ {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
+ {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 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},
+ {AMOVW, C_REG, C_NONE, C_REG, 14, 8, 0},
+ {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0},
+ {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0},
+ {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0},
+ {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0},
- /* 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},
+ {ASUB, C_REG, C_REG, C_REG, 2, 4, 0},
+ {AADD, C_REG, C_REG, C_REG, 2, 4, 0},
+ {AAND, C_REG, C_REG, C_REG, 2, 4, 0},
+ {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0},
+ {AADD, C_REG, C_NONE, C_REG, 2, 4, 0},
+ {AAND, C_REG, C_NONE, C_REG, 2, 4, 0},
- /* 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},
+ {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
+ {ASLL, C_REG, C_REG, C_REG, 9, 4, 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},
+ {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0},
+ {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0},
+ {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0},
+ {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+ {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+ {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 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},
+ {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+ {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 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 */
+ {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+ {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+ {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+ {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
- /* 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},
+ {AMOVW, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVV, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVB, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+ {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+ {AMOVW, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVV, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVB, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+ {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 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
+ {AMOVW, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVV, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVB, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+ {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+ {AMOVW, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVV, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVB, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+ {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+ {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
- Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+ {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+ {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+ {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+ {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+ {AMOVW, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+ {AMOVV, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+ {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+ {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+ {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+ {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+
+ {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
+ {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
+ {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0},
+ {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0},
+
+ {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0},
+ {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0},
+ {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0},
+ {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0},
+ {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0},
+ {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0},
+
+ {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0},
+
+ {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0},
+ {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0},
+ {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0},
+ {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0},
+
+ {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0},
+ {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0},
+ {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0},
+ {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0},
+
+ {AADD, C_UCON, C_REG, C_REG, 25, 8, 0},
+ {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0},
+ {AAND, C_UCON, C_REG, C_REG, 25, 8, 0},
+ {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0},
+
+ {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0},
+ {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0},
+ {AADD, C_LCON, C_REG, C_REG, 23, 12, 0},
+ {AAND, C_LCON, C_REG, C_REG, 23, 12, 0},
+
+ {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0},
+ {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0},
+
+ {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+ {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0},
+ {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+ {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+ {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0},
+
+ {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+ {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+
+ {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO},
+ {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK},
+
+ {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+ {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+ {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+ {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+ {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+
+ {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+ {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+ {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+ {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+ {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+
+ {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+ {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+ {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+ {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+
+ {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+ {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+ {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+ {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+ {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+
+ {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0},
+ {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0},
+ {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0},
+
+ {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0},
+ {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0},
+ {AMOVW, C_UCON, C_NONE, C_FREG, 35, 8, 0},
+ {AMOVW, C_LCON, C_NONE, C_FREG, 36, 12, 0},
+
+ {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0},
+ {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0},
+ {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0},
+ {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0},
+
+ {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0},
+
+ {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+ {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+ {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+ {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+
+ {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */
+ {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+ {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+ {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+ {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+ {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0},
+ {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0},
+ {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0},
+ {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+ {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+ {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+
+ {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0},
}
type Oprang struct {
@@ -406,7 +319,7 @@ var oprange [ALAST & obj.AMask]Oprang
var xcmp [C_NCLASS][C_NCLASS]uint8
-func span9(ctxt *obj.Link, cursym *obj.LSym) {
+func span0(ctxt *obj.Link, cursym *obj.LSym) {
p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
@@ -414,7 +327,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset + 8)
- if oprange[AANDN&obj.AMask].start == nil {
+ if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
@@ -461,25 +374,27 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
o = oplook(ctxt, p)
// very large conditional branches
- if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
+ if o.type_ == 6 && p.Pcond != nil {
otxt = p.Pcond.Pc - c
- if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
+ if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
- q.As = ABR
+ q.As = AJMP
+ q.Lineno = p.Lineno
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.As = AJMP
+ q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = q.Link.Link
- //addnop(p->link);
- //addnop(p);
+ addnop(ctxt, p.Link)
+ addnop(ctxt, p)
bflag = 1
}
}
@@ -509,13 +424,13 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
bp := cursym.P
var i int32
- var out [6]uint32
+ var out [4]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)
+ log.Fatalf("out array in span0 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++ {
@@ -545,32 +460,17 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
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_M0 <= a.Reg && a.Reg <= REG_M31 {
+ return C_MREG
}
- 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 REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
+ return C_FCREG
}
- if a.Reg == REG_FPSCR {
- return C_FPSCR
+ if a.Reg == REG_LO {
+ return C_LO
}
- if a.Reg == REG_MSR {
- return C_MSR
+ if a.Reg == REG_HI {
+ return C_HI
}
return C_GOK
@@ -620,7 +520,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
case obj.TYPE_CONST,
obj.TYPE_ADDR:
switch a.Name {
- case obj.TYPE_NONE:
+ case obj.NAME_NONE:
ctxt.Instoffset = a.Offset
if a.Reg != 0 {
if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
@@ -684,7 +584,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
return C_LCON
}
- return C_DCON
+ return C_LCON // C_DCON
}
if ctxt.Instoffset >= -0x8000 {
@@ -696,7 +596,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
if isint32(ctxt.Instoffset) {
return C_LCON
}
- return C_DCON
+ return C_LCON // C_DCON
case obj.TYPE_BRANCH:
return C_SBRA
@@ -710,6 +610,10 @@ func prasm(p *obj.Prog) {
}
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+ if oprange[AOR&obj.AMask].start == nil {
+ buildop(ctxt)
+ }
+
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1:][0]
@@ -721,29 +625,19 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
}
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 := int(p.To.Class)
+ if a3 == 0 {
+ a3 = aclass(ctxt, &p.To) + 1
+ p.To.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);
+ //print("oplook %P %d %d %d\n", p, a1, a2, a3);
r0 := p.As & obj.AMask
o := oprange[r0].start
@@ -753,21 +647,18 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
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]
- }
+ 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))
+ ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if o == nil {
o = optab
@@ -785,18 +676,25 @@ func cmp(a int, b int) bool {
return true
}
+ case C_ADD0CON:
+ if b == C_ADDCON {
+ return true
+ }
+ fallthrough
+
case C_ADDCON:
if b == C_ZCON || b == C_SCON {
return true
}
- case C_ANDCON:
- if b == C_ZCON || b == C_SCON {
+ case C_AND0CON:
+ if b == C_ANDCON {
return true
}
+ fallthrough
- case C_SPR:
- if b == C_LR || b == C_XER || b == C_CTR {
+ case C_ANDCON:
+ if b == C_ZCON || b == C_SCON {
return true
}
@@ -844,9 +742,6 @@ func cmp(a int, b int) bool {
if b == C_ZOREG {
return true
}
-
- case C_ANY:
- return true
}
return false
@@ -881,10 +776,6 @@ func (x ocmp) Less(i, j int) bool {
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) {
@@ -919,359 +810,118 @@ func buildop(ctxt *obj.Link) {
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)
+ case AABSF:
+ opset(AMOVFD, r0)
+ opset(AMOVDF, r0)
+ opset(AMOVWF, r0)
+ opset(AMOVFW, r0)
+ opset(AMOVWD, r0)
+ opset(AMOVDW, r0)
+ opset(ANEGF, r0)
+ opset(ANEGD, r0)
+ opset(AABSD, r0)
+ opset(ATRUNCDW, r0)
+ opset(ATRUNCFW, r0)
+ opset(ATRUNCDV, r0)
+ opset(ATRUNCFV, r0)
+ opset(AMOVVF, r0)
+ opset(AMOVFV, r0)
+ opset(AMOVVD, r0)
+ opset(AMOVDV, 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)
+ case AADD:
+ opset(ASGT, r0)
+ opset(ASGTU, r0)
+ opset(AADDU, 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)
+ opset(AADDVU, 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 AADDF:
+ opset(ADIVF, r0)
+ opset(ADIVD, r0)
+ opset(AMULF, r0)
+ opset(AMULD, r0)
+ opset(ASUBF, r0)
+ opset(ASUBD, r0)
+ opset(AADDD, r0)
- case AADDC:
- opset(AADDCCC, r0)
+ case AAND:
+ opset(AOR, r0)
+ opset(AXOR, 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 ABLEZ:
+ opset(ABGEZ, r0)
+ opset(ABGEZAL, r0)
+ opset(ABLTZ, r0)
+ opset(ABLTZAL, r0)
+ opset(ABGTZ, r0)
- case ASLD:
- opset(ASLDCC, r0)
- opset(ASRD, r0)
- opset(ASRDCC, r0)
+ case AMOVB:
+ opset(AMOVH, r0)
- case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
- opset(ASRAWCC, r0)
+ case AMOVBU:
+ opset(AMOVHU, r0)
- case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
- opset(ASRADCC, r0)
+ case AMUL:
+ opset(AREM, r0)
+ opset(AREMU, r0)
+ opset(ADIVU, r0)
+ opset(AMULU, r0)
+ opset(ADIV, r0)
+ opset(ADIVV, r0)
+ opset(ADIVVU, r0)
+ opset(AMULV, r0)
+ opset(AMULVU, r0)
+ opset(AREMV, r0)
+ opset(AREMVU, r0)
- case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
- opset(ASUB, r0)
+ case ASLL:
+ opset(ASRL, r0)
+ opset(ASRA, r0)
+ opset(ASLLV, r0)
+ opset(ASRAV, r0)
+ opset(ASRLV, r0)
- opset(ASUBCC, r0)
+ case ASUB:
+ opset(ASUBU, 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)
+ opset(ASUBVU, r0)
+ opset(ANOR, r0)
- case ATLBIE:
- opset(ASLBIE, r0)
- opset(ATLBIEL, r0)
+ case ASYSCALL:
+ opset(ATLBP, r0)
+ opset(ATLBR, r0)
+ opset(ATLBWI, r0)
+ opset(ATLBWR, r0)
- case AEIEIO:
- opset(ASLBIA, r0)
+ case ACMPEQF:
+ opset(ACMPGTF, r0)
+ opset(ACMPGTD, r0)
+ opset(ACMPGEF, r0)
+ opset(ACMPGED, r0)
+ opset(ACMPEQD, r0)
- case ACMP:
- opset(ACMPW, r0)
+ case ABFPT:
+ opset(ABFPF, r0)
- case ACMPU:
- opset(ACMPWU, r0)
+ case AMOVWL:
+ opset(AMOVWR, r0)
+ opset(AMOVVR, r0)
+ opset(AMOVVL, 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,
+ case AMOVW,
+ AMOVD,
+ AMOVF,
+ AMOVV,
+ ABREAK,
+ ARFE,
+ AJAL,
+ AJMP,
+ AMOVWU,
AWORD,
- ADWORD,
obj.ANOP,
obj.ATEXT,
obj.AUNDEF,
@@ -1285,197 +935,60 @@ func buildop(ctxt *obj.Link) {
}
}
-func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
- return o<<26 | xo<<1 | oe<<10 | rc&1
+func OP(x uint32, y uint32) uint32 {
+ return x<<3 | y<<0
}
-func OPCC(o uint32, xo uint32, rc uint32) uint32 {
- return OPVCC(o, xo, 0, rc)
+func SP(x uint32, y uint32) uint32 {
+ return x<<29 | y<<26
}
-func OP(o uint32, xo uint32) uint32 {
- return OPVCC(o, xo, 0, 0)
+func BCOND(x uint32, y uint32) uint32 {
+ return x<<19 | y<<16
}
-/* 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 MMU(x uint32, y uint32) uint32 {
+ return SP(2, 0) | 16<<21 | x<<3 | y<<0
}
-func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
- return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
+func FPF(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 16<<21 | x<<3 | y<<0
}
-func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
- return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
+func FPD(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 17<<21 | x<<3 | y<<0
}
-func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
- return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
+func FPW(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 20<<21 | x<<3 | y<<0
}
-func OP_BR(op uint32, li uint32, aa uint32) uint32 {
- return op | li&0x03FFFFFC | aa<<1
+func FPV(x uint32, y uint32) uint32 {
+ return SP(2, 1) | 21<<21 | x<<3 | y<<0
}
-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_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
}
-func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
- return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
+func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
+ return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<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 OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
}
-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 OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+ return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
}
-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 OP_JMP(op uint32, i uint32) uint32 {
+ return op | i&0x3FFFFFF
}
-func high16adjusted(d int32) uint16 {
- if d&0x8000 != 0 {
- return uint16((d >> 16) + 1)
- }
- return uint16(d >> 16)
+func oclass(a *obj.Addr) int {
+ return int(a.Class) - 1
}
func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
@@ -1483,934 +996,412 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
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_)
+ ctxt.Diag("unknown type %d %v", 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)
- }
+ case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
+ o1 = OP_RRR(oprrr(ctxt, AOR), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
- 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 */
+ case 2: /* add/sub r1,[r2],r3 */
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))
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
- case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
- d := vregoff(ctxt, &p.From)
+ case 3: /* mov $soreg, r ==> or/add $i,o,r */
+ v := regoff(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 := AADDVU
+ if o.a1 == C_ANDCON {
+ a = AOR
}
- 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 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
- o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
-
- case 4: /* add/mul $scon,[r1],r2 */
+ case 4: /* add $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))
+
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
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)
+ case 6: /* beq r1,[r2],sbra */
+ v := int32(0)
+ if p.Pcond == nil {
+ v = int32(-4) >> 2
+ } else {
+ v = int32(p.Pcond.Pc-p.Pc-4) >> 2
}
- o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+ if (v<<16)>>16 != v {
+ ctxt.Diag("short branch too far\n%v", p)
+ }
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
+ // for ABFPT and ABFPF only: always fill delay slot with 0
+ // see comments in func preprocess for details.
+ o2 = 0
- case 7: /* mov r, soreg ==> stw o(r) */
+ case 7: /* mov r, soreg ==> sw 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))
- }
+ o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.From.Reg))
- case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
+ case 8: /* mov soreg, r ==> lw 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))
- }
+ o1 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(v), uint32(r), uint32(p.To.Reg))
- 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 */
+ case 9: /* sll r1,[r2],r3 */
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)
- }
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
- 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 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
+ v := regoff(ctxt, &p.From)
+ a := AOR
+ if v < 0 {
+ a = AADDU
}
-
- case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
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 */
- }
+ o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- 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
- }
+ case 11: /* jmp 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<<16) || v >= 1<<15 {
- ctxt.Diag("branch too far\n%v", p)
+ if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
+ // use PC-relative branch for short branches
+ // BEQ R0, R0, sbra
+ if p.Pcond == nil {
+ v = int32(-4) >> 2
+ } else {
+ v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+ }
+ if (v<<16)>>16 == v {
+ o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
+ break
+ }
}
- 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
+ if p.Pcond == nil {
+ v = int32(p.Pc) >> 2
} else {
- v = 20 /* unconditional */
+ v = int32(p.Pcond.Pc) >> 2
}
- 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
+ o1 = OP_JMP(opirr(ctxt, int(p.As)), uint32(v))
+ if p.To.Sym == nil {
+ p.To.Sym = ctxt.Cursym.Text.From.Sym
+ p.To.Offset = p.Pcond.Pc
}
- 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
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+ if p.As == AJAL {
+ rel.Type = obj.R_CALLMIPS
} else {
- v = 20 /* unconditional */
- }
- r := int(p.Reg)
- if r == 0 {
- r = 0
+ rel.Type = obj.R_JMPMIPS
}
- 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
+ case 12: /* movbs r,r */
+ v := 16
+ if p.As == AMOVB {
+ v = 24
}
+ o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
+ o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
- if p.As == ABL || p.As == ABCL {
- o1 |= 1
+ case 13: /* movbu r,r */
+ if p.As == AMOVBU {
+ o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
+ } else {
+ o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
}
- 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)))
+ case 14: /* movwu r,r */
+ o1 = OP_SRR(opirr(ctxt, ASLLV+ALAST), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
+ if p.As == AMOVWU {
+ o2 = OP_SRR(opirr(ctxt, ASRLV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
} 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)
+ o2 = OP_SRR(opirr(ctxt, ASRAV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
}
- //if(dlm) reloc(&p->from, p->pc, 0);
-
- case 20: /* add $ucon,,r */
+ case 16: /* sll $c,[r1],r2 */
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)
+ /* OP_SRR will use only the low 5 bits of the shift value */
+ if v >= 32 && vshift(p.As) {
+ o1 = OP_SRR(opirr(ctxt, int(p.As)+ALAST), uint32(v-32), uint32(r), uint32(p.To.Reg))
+ } else {
+ o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
}
- //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
- }
+ case 18: /* jmp [r1],0(r2) */
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);
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.To.Reg), uint32(r))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 0
+ rel.Type = obj.R_CALLIND
- case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
+ case 19: /* mov $lcon,r ==> lu+or */
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)
- }
-
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
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
+ rel.Type = obj.R_ADDRMIPS
}
- case 32: /* fmul frc,fra,frd */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ case 20: /* mov lo/hi,r */
+ a := OP(2, 0) /* mfhi */
+ if p.From.Reg == REG_LO {
+ a = OP(2, 2) /* mflo */
}
- 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)
+ o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
- if oclass(&p.From) == C_NONE {
- r = int(p.To.Reg)
+ case 21: /* mov r,lo/hi */
+ a := OP(2, 1) /* mthi */
+ if p.To.Reg == REG_LO {
+ a = OP(2, 3) /* mtlo */
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r))
+ o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
- 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 22: /* mul r1,r2 */
+ o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
- 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)
+ case 23: /* add $lcon,r1,r2 ==> lu+or+add */
+ v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ r := int(p.Reg)
if r == 0 {
- r = int(o.param)
+ r = int(p.To.Reg)
}
- 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))
+ o3 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
+ case 24: /* mov $ucon,r ==> lu r */
v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
- r := int(p.From.Reg)
+ case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
+ v := regoff(ctxt, &p.From)
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ r := int(p.Reg)
if r == 0 {
- r = int(o.param)
+ r = int(p.To.Reg)
}
- 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))
+ o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
+ case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
v := regoff(ctxt, &p.From)
-
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
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))
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
- 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 */
+ case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
+ v := regoff(ctxt, &p.From)
r := int(p.From.Reg)
-
if r == 0 {
- r = int(p.To.Reg)
+ r = int(o.param)
}
- 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)
+ a := AMOVF + ALAST
+ if p.As == AMOVD {
+ a = AMOVD + ALAST
}
- o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+ switch o.size {
+ case 16:
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(r), uint32(p.To.Reg))
- 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 4:
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
}
- case 50: /* rem[u] r1[,r2],r3 */
- r := int(p.Reg)
-
+ case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
+ v := regoff(ctxt, &p.To)
+ r := int(p.To.Reg)
if r == 0 {
- r = int(p.To.Reg)
+ r = int(o.param)
}
- 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
+ a := AMOVF
+ if p.As == AMOVD {
+ a = AMOVD
}
+ switch o.size {
+ case 16:
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
- case 51: /* remd[u] r1[,r2],r3 */
- r := int(p.Reg)
-
- if r == 0 {
- r = int(p.To.Reg)
+ case 4:
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.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 30: /* movw r,fr */
+ a := SP(2, 1) | (4 << 21) /* mtc1 */
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
- case 57: /* slw $sh,[s,]a -> rlwinm ... */
- v := regoff(ctxt, &p.From)
+ case 31: /* movw fr,r */
+ a := SP(2, 1) | (0 << 21) /* mtc1 */
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+ case 32: /* fadd fr1,[fr2],fr3 */
r := int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
+ o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(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 33: /* fabs fr1, fr3 */
+ o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
- case 58: /* logical $andcon,[s],a */
+ case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
v := regoff(ctxt, &p.From)
-
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
+ a := AADDU
+ if o.a1 == C_ANDCON {
+ a = AOR
}
- 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)
+ o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
+ o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
- r := int(p.Reg)
+ case 35: /* mov r,lext/auto/oreg ==> sw o(r) */
+ v := regoff(ctxt, &p.To)
+ r := int(p.To.Reg)
if r == 0 {
- r = int(p.To.Reg)
+ r = int(o.param)
}
- 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))
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.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 */
+ case 36: /* mov lext/auto/oreg,r ==> lw o(r30) */
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
+ r := int(p.From.Reg)
+ if r == 0 {
+ r = int(o.param)
}
- o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+ o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+ o4 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), 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
+ case 37: /* movw r,mr */
+ a := SP(2, 0) | (4 << 21) /* mtc0 */
+ if p.As == AMOVV {
+ a = SP(2, 0) | (5 << 21) /* dmtc0 */
}
- 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))
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(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)
+ case 38: /* movw mr,r */
+ a := SP(2, 0) | (0 << 21) /* mfc0 */
+ if p.As == AMOVV {
+ a = SP(2, 0) | (1 << 21) /* dmfc0 */
}
- o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0)
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
- 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)
+ case 40: /* word */
+ o1 = uint32(regoff(ctxt, &p.From))
- 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)
+ case 41: /* movw f,fcr */
+ o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */
+ o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
- //if(dlm) reloc(&p->to, p->pc, 1);
+ case 42: /* movw fcr,r */
+ o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
- 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)
+ case 47: /* movv r,fr */
+ a := SP(2, 1) | (5 << 21) /* dmtc1 */
+ o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
- //if(dlm) reloc(&p->from, p->pc, 1);
+ case 48: /* movv fr,r */
+ a := SP(2, 1) | (1 << 21) /* dmtc1 */
+ o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
- 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)
+ case 49: /* undef */
+ o1 = 8 /* JMP (R0) */
- //if(dlm) reloc(&p->from, p->pc, 1);
+ /* relocation operations */
+ case 50: /* mov r,addr ==> lu + or + sw (REGTMP) */
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+ rel := obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+ rel.Type = obj.R_ADDRMIPS
+ o3 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+ case 51: /* mov addr,r ==> lu + or + lw (REGTMP) */
+ o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+ o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+ 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_ADDRMIPS
+ o3 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
}
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)
- }
+ aclass(ctxt, a)
return ctxt.Instoffset
}
@@ -2418,827 +1409,325 @@ func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
return int32(vregoff(ctxt, a))
}
-func oprrr(ctxt *obj.Link, a int) int32 {
+func oprrr(ctxt *obj.Link, a int) uint32 {
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))
-
+ return OP(4, 0)
+ case AADDU:
+ return OP(4, 1)
+ case ASGT:
+ return OP(5, 2)
+ case ASGTU:
+ return OP(5, 3)
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))
+ return OP(4, 4)
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))
-
+ return OP(4, 5)
+ case AXOR:
+ return OP(4, 6)
case ASUB:
- return int32(OPVCC(31, 40, 0, 0))
- case ASUBCC:
- return int32(OPVCC(31, 40, 0, 1))
+ return OP(4, 2)
+ case ASUBU:
+ return OP(4, 3)
+ case ANOR:
+ return OP(4, 7)
+ case ASLL:
+ return OP(0, 4)
+ case ASRL:
+ return OP(0, 6)
+ case ASRA:
+ return OP(0, 7)
+ case ASLLV:
+ return OP(2, 4)
+ case ASRLV:
+ return OP(2, 6)
+ case ASRAV:
+ return OP(2, 7)
+ case AADDV:
+ return OP(5, 4)
+ case AADDVU:
+ return OP(5, 5)
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))
+ return OP(5, 6)
+ case ASUBVU:
+ return OP(5, 7)
+ case AREM,
+ ADIV:
+ return OP(3, 2)
+ case AREMU,
+ ADIVU:
+ return OP(3, 3)
+ case AMUL:
+ return OP(3, 0)
+ case AMULU:
+ return OP(3, 1)
+ case AREMV,
+ ADIVV:
+ return OP(3, 6)
+ case AREMVU,
+ ADIVVU:
+ return OP(3, 7)
+ case AMULV:
+ return OP(3, 4)
+ case AMULVU:
+ return OP(3, 5)
- case ASYNC:
- return int32(OPVCC(31, 598, 0, 0))
- case APTESYNC:
- return int32(OPVCC(31, 598, 0, 0) | 2<<21)
+ case AJMP:
+ return OP(1, 0)
+ case AJAL:
+ return OP(1, 1)
- 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 ABREAK:
+ return OP(1, 5)
+ case ASYSCALL:
+ return OP(1, 4)
+ case ATLBP:
+ return MMU(1, 0)
+ case ATLBR:
+ return MMU(0, 1)
+ case ATLBWI:
+ return MMU(0, 2)
+ case ATLBWR:
+ return MMU(0, 6)
+ case ARFE:
+ return MMU(2, 0)
- case AXOR:
- return int32(OPVCC(31, 316, 0, 0))
- case AXORCC:
- return int32(OPVCC(31, 316, 0, 1))
+ case ADIVF:
+ return FPF(0, 3)
+ case ADIVD:
+ return FPD(0, 3)
+ case AMULF:
+ return FPF(0, 2)
+ case AMULD:
+ return FPD(0, 2)
+ case ASUBF:
+ return FPF(0, 1)
+ case ASUBD:
+ return FPD(0, 1)
+ case AADDF:
+ return FPF(0, 0)
+ case AADDD:
+ return FPD(0, 0)
+ case ATRUNCFV:
+ return FPF(1, 1)
+ case ATRUNCDV:
+ return FPD(1, 1)
+ case ATRUNCFW:
+ return FPF(1, 5)
+ case ATRUNCDW:
+ return FPD(1, 5)
+ case AMOVFV:
+ return FPF(4, 5)
+ case AMOVDV:
+ return FPD(4, 5)
+ case AMOVVF:
+ return FPV(4, 0)
+ case AMOVVD:
+ return FPV(4, 1)
+ case AMOVFW:
+ return FPF(4, 4)
+ case AMOVDW:
+ return FPD(4, 4)
+ case AMOVWF:
+ return FPW(4, 0)
+ case AMOVDF:
+ return FPD(4, 0)
+ case AMOVWD:
+ return FPW(4, 1)
+ case AMOVFD:
+ return FPF(4, 1)
+ case AABSF:
+ return FPF(0, 5)
+ case AABSD:
+ return FPD(0, 5)
+ case AMOVF:
+ return FPF(0, 6)
+ case AMOVD:
+ return FPD(0, 6)
+ case ANEGF:
+ return FPF(0, 7)
+ case ANEGD:
+ return FPD(0, 7)
+ case ACMPEQF:
+ return FPF(6, 2)
+ case ACMPEQD:
+ return FPD(6, 2)
+ case ACMPGTF:
+ return FPF(7, 4)
+ case ACMPGTD:
+ return FPD(7, 4)
+ case ACMPGEF:
+ return FPF(7, 6)
+ case ACMPGED:
+ return FPD(7, 6)
}
- ctxt.Diag("bad r/r opcode %v", obj.Aconv(a))
+ if a >= ALAST {
+ ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST))
+ } else {
+ ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
+ }
return 0
}
-func opirr(ctxt *obj.Link, a int) int32 {
+func opirr(ctxt *obj.Link, a int) uint32 {
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))
-
+ return SP(1, 0)
+ case AADDU:
+ return SP(1, 1)
+ case ASGT:
+ return SP(1, 2)
+ case ASGTU:
+ return SP(1, 3)
+ case AAND:
+ return SP(1, 4)
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))
-
+ return SP(1, 5)
case AXOR:
- return int32(OPVCC(26, 0, 0, 0)) /* XORIL */
- case AXOR + ALAST:
- return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
- }
+ return SP(1, 6)
+ case ALAST:
+ return SP(1, 7) /* lui */
+ case ASLL:
+ return OP(0, 0)
+ case ASRL:
+ return OP(0, 2)
+ case ASRA:
+ return OP(0, 3)
+ case AADDV:
+ return SP(3, 0)
+ case AADDVU:
+ return SP(3, 1)
- ctxt.Diag("bad opcode i/r %v", obj.Aconv(a))
- return 0
-}
+ case AJMP:
+ return SP(0, 2)
+ case AJAL,
+ obj.ADUFFZERO,
+ obj.ADUFFCOPY:
+ return SP(0, 3)
+ case ABEQ:
+ return SP(0, 4)
+ case ABEQ + ALAST:
+ return SP(2, 4) /* likely */
+ case ABNE:
+ return SP(0, 5)
+ case ABNE + ALAST:
+ return SP(2, 5) /* likely */
+ case ABGEZ:
+ return SP(0, 1) | BCOND(0, 1)
+ case ABGEZ + ALAST:
+ return SP(0, 1) | BCOND(0, 3) /* likely */
+ case ABGEZAL:
+ return SP(0, 1) | BCOND(2, 1)
+ case ABGEZAL + ALAST:
+ return SP(0, 1) | BCOND(2, 3) /* likely */
+ case ABGTZ:
+ return SP(0, 7)
+ case ABGTZ + ALAST:
+ return SP(2, 7) /* likely */
+ case ABLEZ:
+ return SP(0, 6)
+ case ABLEZ + ALAST:
+ return SP(2, 6) /* likely */
+ case ABLTZ:
+ return SP(0, 1) | BCOND(0, 0)
+ case ABLTZ + ALAST:
+ return SP(0, 1) | BCOND(0, 2) /* likely */
+ case ABLTZAL:
+ return SP(0, 1) | BCOND(2, 0)
+ case ABLTZAL + ALAST:
+ return SP(0, 1) | BCOND(2, 2) /* likely */
+ case ABFPT:
+ return SP(2, 1) | (257 << 16)
+ case ABFPT + ALAST:
+ return SP(2, 1) | (259 << 16) /* likely */
+ case ABFPF:
+ return SP(2, 1) | (256 << 16)
+ case ABFPF + ALAST:
+ return SP(2, 1) | (258 << 16) /* likely */
-/*
- * load o(a),d
- */
-func opload(ctxt *obj.Link, a int) int32 {
- switch a {
+ case AMOVB,
+ AMOVBU:
+ return SP(5, 0)
+ case AMOVH,
+ AMOVHU:
+ return SP(5, 1)
+ case AMOVW,
+ AMOVWU:
+ return SP(5, 3)
+ case AMOVV:
+ return SP(7, 7)
+ case AMOVF:
+ return SP(7, 1)
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 */
- }
+ return SP(7, 5)
+ case AMOVWL:
+ return SP(5, 2)
+ case AMOVWR:
+ return SP(5, 6)
+ case AMOVVL:
+ return SP(5, 4)
+ case AMOVVR:
+ return SP(5, 5)
- ctxt.Diag("bad load opcode %v", obj.Aconv(a))
- return 0
-}
+ case ABREAK:
+ return SP(5, 7)
-/*
- * 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 AMOVWL + ALAST:
+ return SP(4, 2)
+ case AMOVWR + ALAST:
+ return SP(4, 6)
+ case AMOVVL + ALAST:
+ return SP(3, 2)
+ case AMOVVR + ALAST:
+ return SP(3, 3)
+ case AMOVB + ALAST:
+ return SP(4, 0)
+ case AMOVBU + ALAST:
+ return SP(4, 4)
+ case AMOVH + ALAST:
+ return SP(4, 1)
+ case AMOVHU + ALAST:
+ return SP(4, 5)
+ case AMOVW + ALAST:
+ return SP(4, 3)
+ case AMOVWU + ALAST:
+ return SP(4, 7)
+ case AMOVV + ALAST:
+ return SP(6, 7)
+ case AMOVF + ALAST:
+ return SP(6, 1)
+ case AMOVD + ALAST:
+ return SP(6, 5)
- 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 */
+ case ASLLV:
+ return OP(7, 0)
+ case ASRLV:
+ return OP(7, 2)
+ case ASRAV:
+ return OP(7, 3)
+ case ASLLV + ALAST:
+ return OP(7, 4)
+ case ASRLV + ALAST:
+ return OP(7, 6)
+ case ASRAV + ALAST:
+ return OP(7, 7)
}
- 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 */
+ if a >= ALAST {
+ ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST))
+ } else {
+ ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
}
-
- ctxt.Diag("unknown store opcode %v", obj.Aconv(a))
return 0
}
-/*
- * indexed store s,a(b)
- */
-func opstorex(ctxt *obj.Link, a int) int32 {
+func vshift(a int16) bool {
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 */
+ case ASLLV,
+ ASRLV,
+ ASRAV:
+ return true
}
-
- ctxt.Diag("unknown storex opcode %v", obj.Aconv(a))
- return 0
+ return false
}
diff --git a/src/cmd/internal/obj/mips/list0.go b/src/cmd/internal/obj/mips/list0.go
index 4cdcfbcd27..0807a62a8d 100644
--- a/src/cmd/internal/obj/mips/list0.go
+++ b/src/cmd/internal/obj/mips/list0.go
@@ -27,7 +27,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
@@ -35,8 +35,8 @@ import (
)
func init() {
- obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, Rconv)
- obj.RegisterOpcode(obj.ABasePPC64, Anames)
+ obj.RegisterRegister(obj.RBaseMIPS64, REG_FCR0+1024, Rconv)
+ obj.RegisterOpcode(obj.ABaseMIPS64, Anames)
}
func Rconv(r int) string {
@@ -53,44 +53,26 @@ func Rconv(r int) string {
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 REG_M0 <= r && r <= REG_M31 {
+ return fmt.Sprintf("M%d", r-REG_M0)
}
- if r == REG_CR {
- return "CR"
+ if REG_FCR0 <= r && r <= REG_FCR31 {
+ return fmt.Sprintf("FCR%d", r-REG_FCR0)
}
- 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_HI {
+ return "HI"
}
- if r == REG_MSR {
- return "MSR"
+ if r == REG_LO {
+ return "LO"
}
- return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64)
+ return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64)
}
func DRconv(a int) string {
s := "C_??"
if a >= C_NONE && a <= C_NCLASS {
- s = cnames9[a]
+ s = cnames0[a]
}
var fp string
fp += s
diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go
index 1eddc6fc6c..a3ccad2764 100644
--- a/src/cmd/internal/obj/mips/obj0.go
+++ b/src/cmd/internal/obj/mips/obj0.go
@@ -27,7 +27,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package ppc64
+package mips
import (
"cmd/internal/obj"
@@ -40,11 +40,11 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
p.From.Class = 0
p.To.Class = 0
- // Rewrite BR/BL to symbol as TYPE_BRANCH.
+ // Rewrite JMP/JAL to symbol as TYPE_BRANCH.
switch p.As {
- case ABR,
- ABL,
- obj.ARET,
+ case AJMP,
+ AJAL,
+ ARET,
obj.ADUFFZERO,
obj.ADUFFCOPY:
if p.To.Sym != nil {
@@ -54,7 +54,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// Rewrite float constants to values stored in memory.
switch p.As {
- case AFMOVS:
+ case AMOVF:
if p.From.Type == obj.TYPE_FCONST {
f32 := float32(p.From.Val.(float64))
i32 := math.Float32bits(f32)
@@ -67,7 +67,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
p.From.Offset = 0
}
- case AFMOVD:
+ case AMOVD:
if p.From.Type == obj.TYPE_FCONST {
i64 := math.Float64bits(p.From.Val.(float64))
literal := fmt.Sprintf("$f64.%016x", i64)
@@ -80,7 +80,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
}
// Put >32-bit constants in memory and load them
- case AMOVD:
+ case AMOVV:
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)
@@ -94,22 +94,28 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// Rewrite SUB constants into ADD.
switch p.As {
- case ASUBC:
+ case ASUB:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADDC
+ p.As = AADD
}
- case ASUBCCC:
+ case ASUBU:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADDCCC
+ p.As = AADDU
}
- case ASUB:
+ case ASUBV:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
- p.As = AADD
+ p.As = AADDV
+ }
+
+ case ASUBVU:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Offset = -p.From.Offset
+ p.As = AADDVU
}
}
}
@@ -118,6 +124,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
+ // a switch for enabling/disabling instruction scheduling
+ nosched := true
+
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
@@ -152,112 +161,65 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p.Link.Mark |= LABEL
}
- case ANOR:
+ /* too hard, just leave alone */
+ case AMOVW,
+ AMOVV:
q = p
- if p.To.Type == obj.TYPE_REG {
- if p.To.Reg == REGZERO {
- p.Mark |= LABEL | SYNC
- }
+ if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
+ p.Mark |= LABEL | SYNC
+ break
+ }
+ if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
+ 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,
+ /* too hard, just leave alone */
+ case ASYSCALL,
AWORD,
- ARFI,
- ARFCI,
- ARFID,
- AHRFID:
+ ATLBWR,
+ ATLBWI,
+ ATLBP,
+ ATLBR:
q = p
p.Mark |= LABEL | SYNC
- continue
- case AMOVW, AMOVWZ, AMOVD:
+ case ANOR:
q = p
- if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
- p.Mark |= LABEL | SYNC
+ if p.To.Type == obj.TYPE_REG {
+ if p.To.Reg == REGZERO {
+ 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,
+ case ABGEZAL,
+ ABLTZAL,
+ AJAL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF
fallthrough
- case ABC,
+ case AJMP,
ABEQ,
- ABGE,
- ABGT,
- ABLE,
- ABLT,
+ ABGEZ,
+ ABGTZ,
+ ABLEZ,
+ ABLTZ,
ABNE,
- ABR,
- ABVC,
- ABVS:
- p.Mark |= BRANCH
+ ABFPT, ABFPF:
+ if p.As == ABFPT || p.As == ABFPF {
+ // We don't treat ABFPT and ABFPF as branches here,
+ // so that we will always fill nop (0x0) in their
+ // delay slot during assembly.
+ // This is to workaround a kernel FPU emulator bug
+ // where it uses the user stack to simulate the
+ // instruction in the delay slot if it's not 0x0,
+ // and somehow that leads to SIGSEGV when the kernel
+ // jump to the stack.
+ p.Mark |= SYNC
+ } else {
+ p.Mark |= BRANCH
+ }
q = p
q1 = p.Pcond
if q1 != nil {
@@ -269,21 +231,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if q1.Mark&LEAF == 0 {
q1.Mark |= LABEL
}
- } else {
- p.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:
+ case ARET:
q = p
if p.Link != nil {
p.Link.Mark |= LABEL
@@ -303,8 +261,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
autosize := int32(0)
- var aoffset int
- var mov int
var o int
var p1 *obj.Prog
var p2 *obj.Prog
@@ -312,8 +268,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
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
@@ -329,27 +283,23 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
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
- }
+ q = obj.Appendp(ctxt, p)
+ q.As = AADDV
+ 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()
- }
+ if cursym.Text.From3.Offset&obj.NOSPLIT != 0 {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+ ctxt.Bso.Flush()
+ }
- cursym.Text.Mark |= LEAF
+ cursym.Text.Mark |= LEAF
+ }
}
if cursym.Text.Mark&LEAF != 0 {
@@ -358,106 +308,86 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
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.As = AMOVV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_REG
- q.From.Reg = REGTMP
+ q.From.Reg = REGLINK
q.To.Type = obj.TYPE_MEM
- q.To.Offset = int64(aoffset)
+ q.To.Offset = int64(0)
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)
+ // MOVV g_panic(g), R1
+ // BEQ R1, end
+ // MOVV panic_argp(R1), R2
+ // ADDV $(autosize+8), R29, R3
+ // BNE R2, R3, end
+ // ADDV $8, R29, R2
+ // MOVV R2, panic_argp(R1)
// 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.
+ // It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes.
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
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.To.Reg = REG_R1
q = obj.Appendp(ctxt, q)
q.As = ABEQ
+ q.From.Type = obj.TYPE_REG
+ q.From.Reg = REG_R1
q.To.Type = obj.TYPE_BRANCH
+ q.Mark |= BRANCH
p1 = q
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
q.From.Type = obj.TYPE_MEM
- q.From.Reg = REG_R3
+ q.From.Reg = REG_R1
q.From.Offset = 0 // Panic.argp
q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_R4
+ q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
- q.As = AADD
+ q.As = AADDV
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.To.Reg = REG_R3
q = obj.Appendp(ctxt, q)
q.As = ABNE
+ q.From.Type = obj.TYPE_REG
+ q.From.Reg = REG_R2
+ q.Reg = REG_R3
q.To.Type = obj.TYPE_BRANCH
+ q.Mark |= BRANCH
p2 = q
q = obj.Appendp(ctxt, q)
- q.As = AADD
+ q.As = AADDV
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.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
- q.As = AMOVD
+ q.As = AMOVV
q.From.Type = obj.TYPE_REG
- q.From.Reg = REG_R6
+ q.From.Reg = REG_R2
q.To.Type = obj.TYPE_MEM
- q.To.Reg = REG_R3
+ q.To.Reg = REG_R1
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(ctxt, q)
@@ -467,29 +397,30 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p2.Pcond = q
}
- case obj.ARET:
+ case 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.As = AJMP
p.To.Type = obj.TYPE_BRANCH
break
}
if cursym.Text.Mark&LEAF != 0 {
if autosize == 0 {
- p.As = ABR
+ p.As = AJMP
p.From = obj.Addr{}
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_LR
+ p.To.Type = obj.TYPE_MEM
+ p.To.Offset = 0
+ p.To.Reg = REGLINK
p.Mark |= BRANCH
break
}
- p.As = AADD
+ p.As = AADDV
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize)
p.To.Type = obj.TYPE_REG
@@ -497,10 +428,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p.Spadj = -autosize
q = ctxt.NewProg()
- q.As = ABR
+ q.As = AJMP
q.Lineno = p.Lineno
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REG_LR
+ q.To.Type = obj.TYPE_MEM
+ q.To.Offset = 0
+ q.To.Reg = REGLINK
q.Mark |= BRANCH
q.Spadj = +autosize
@@ -509,34 +441,22 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
break
}
- p.As = AMOVD
+ p.As = AMOVV
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
+ p.To.Reg = REG_R4
if false {
// Debug bad returns
q = ctxt.NewProg()
- q.As = AMOVD
+ q.As = AMOVV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_MEM
q.From.Offset = 0
- q.From.Reg = REGTMP
+ q.From.Reg = REG_R4
q.To.Type = obj.TYPE_REG
q.To.Reg = REGTMP
@@ -547,7 +467,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if autosize != 0 {
q = ctxt.NewProg()
- q.As = AADD
+ q.As = AADDV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(autosize)
@@ -560,74 +480,84 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
q1 = ctxt.NewProg()
- q1.As = ABR
+ q1.As = AJMP
q1.Lineno = p.Lineno
- q1.To.Type = obj.TYPE_REG
- q1.To.Reg = REG_LR
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Offset = 0
+ q1.To.Reg = REG_R4
q1.Mark |= BRANCH
q1.Spadj = +autosize
q1.Link = q.Link
q.Link = q1
- case AADD:
+ case AADDV,
+ AADDVU:
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;
+ if nosched {
+ // if we don't do instruction scheduling, simply add
+ // NOP after each branch instruction.
+ for p = cursym.Text; p != nil; p = p.Link {
+ if p.Mark&BRANCH != 0 {
+ addnop(ctxt, p)
+ }
+ }
+ 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);
+ // instruction scheduling
+ q = nil // p - 1
+ q1 = cursym.Text // top of block
+ o = 0 // count of instructions
+ for p = cursym.Text; p != nil; p = p1 {
+ p1 = p.Link
+ o++
+ if p.Mark&NOSCHED != 0 {
+ if q1 != p {
+ sched(ctxt, q1, q)
}
- for(; p != nil; p = p->link){
- if(!(p->mark & NOSCHED))
- break;
- q = p;
+ for ; p != nil; p = p.Link {
+ if p.Mark&NOSCHED == 0 {
+ break
+ }
+ q = p
}
- p1 = p;
- q1 = p;
- o = 0;
- continue;
+ 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&(LABEL|SYNC) != 0 {
+ if q1 != p {
+ sched(ctxt, q1, q)
+ }
+ q1 = p
+ o = 1
}
- if(p->mark & (BRANCH|SYNC)) {
- sched(q1, p);
- q1 = p1;
- o = 0;
+ if p.Mark&(BRANCH|SYNC) != 0 {
+ sched(ctxt, q1, p)
+ q1 = p1
+ o = 0
}
- if(o >= NSCHED) {
- sched(q1, p);
- q1 = p1;
- o = 0;
+ if o >= NSCHED {
+ sched(ctxt, q1, p)
+ q1 = p1
+ o = 0
}
- q = p;
+ q = p
}
-*/
+}
+
func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
- // MOVD g_stackguard(g), R3
+ // MOVV g_stackguard(g), R1
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_MEM
p.From.Reg = REGG
p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
@@ -635,38 +565,40 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
}
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R3
+ p.To.Reg = REG_R1
var q *obj.Prog
if framesize <= obj.StackSmall {
// small stack: SP < stackguard
- // CMP stackguard, SP
+ // AGTU SP, stackguard, R1
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REGSP
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGSP
+ p.To.Reg = REG_R1
} else if framesize <= obj.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
- // ADD $-framesize, SP, R4
- // CMP stackguard, R4
+ // ADDV $-framesize, SP, R2
+ // SGTU R2, stackguard, R1
p = obj.Appendp(ctxt, p)
- p.As = AADD
+ p.As = AADDV
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.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REG_R2
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R1
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
@@ -676,79 +608,88 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
//
// 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
+ // // stackguard is R1
+ // MOVV $StackPreempt, R2
+ // BEQ R1, R2, label-of-call-to-morestack
+ // ADDV $StackGuard, SP, R2
+ // SUBVU R1, R2
+ // MOVV $(framesize+(StackGuard-StackSmall)), R1
+ // SGTU R2, R1, R1
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.As = AMOVV
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = obj.StackPreempt
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
q = p
p.As = ABEQ
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R1
+ p.Reg = REG_R2
p.To.Type = obj.TYPE_BRANCH
+ p.Mark |= BRANCH
p = obj.Appendp(ctxt, p)
- p.As = AADD
+ p.As = AADDV
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.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = ASUB
+ p.As = ASUBVU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_R3
+ p.From.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R2
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
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.To.Reg = REG_R1
p = obj.Appendp(ctxt, p)
- p.As = ACMPU
+ p.As = ASGTU
p.From.Type = obj.TYPE_REG
- p.From.Reg = REGTMP
+ p.From.Reg = REG_R2
+ p.Reg = REG_R1
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R4
+ p.To.Reg = REG_R1
}
- // q1: BLT done
+ // q1: BNE R1, done
p = obj.Appendp(ctxt, p)
q1 := p
- p.As = ABLT
+ p.As = ABNE
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = REG_R1
p.To.Type = obj.TYPE_BRANCH
+ p.Mark |= BRANCH
- // MOVD LR, R5
+ // MOVV LINK, R3
p = obj.Appendp(ctxt, p)
- p.As = AMOVD
+ p.As = AMOVV
p.From.Type = obj.TYPE_REG
- p.From.Reg = REG_LR
+ p.From.Reg = REGLINK
p.To.Type = obj.TYPE_REG
- p.To.Reg = REG_R5
+ p.To.Reg = REG_R3
if q != nil {
q.Pcond = p
+ p.Mark |= LABEL
}
- // BL runtime.morestack(SB)
+ // JAL runtime.morestack(SB)
p = obj.Appendp(ctxt, p)
- p.As = ABL
+ p.As = AJAL
p.To.Type = obj.TYPE_BRANCH
if ctxt.Cursym.Cfunc != 0 {
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
@@ -757,13 +698,15 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
} else {
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
}
+ p.Mark |= BRANCH
- // BR start
+ // JMP start
p = obj.Appendp(ctxt, p)
- p.As = ABR
+ p.As = AJMP
p.To.Type = obj.TYPE_BRANCH
p.Pcond = ctxt.Cursym.Text.Link
+ p.Mark |= BRANCH
// placeholder for q1's jump target
p = obj.Appendp(ctxt, p)
@@ -774,47 +717,632 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
return p
}
-func follow(ctxt *obj.Link, s *obj.LSym) {
- ctxt.Cursym = s
+func addnop(ctxt *obj.Link, p *obj.Prog) {
+ q := ctxt.NewProg()
+ // we want to use the canonical NOP (SLL $0,R0,R0) here,
+ // however, as the assembler will always replace $0
+ // as R0, we have to resort to manually encode the SLL
+ // instruction as WORD $0.
+ q.As = AWORD
+ q.Lineno = p.Lineno
+ q.From.Type = obj.TYPE_CONST
+ q.From.Name = obj.NAME_NONE
+ q.From.Offset = 0
- firstp := ctxt.NewProg()
- lastp := firstp
- xfol(ctxt, s.Text, &lastp)
- lastp.Link = nil
- s.Text = firstp.Link
+ q.Link = p.Link
+ p.Link = q
+}
+
+const (
+ E_HILO = 1 << 0
+ E_FCR = 1 << 1
+ E_MCR = 1 << 2
+ E_MEM = 1 << 3
+ E_MEMSP = 1 << 4 /* uses offset and size */
+ E_MEMSB = 1 << 5 /* uses offset and size */
+ ANYMEM = E_MEM | E_MEMSP | E_MEMSB
+ //DELAY = LOAD|BRANCH|FCMP
+ DELAY = BRANCH /* only schedule branch */
+)
+
+type Dep struct {
+ ireg uint32
+ freg uint32
+ cc uint32
+}
+
+type Sch struct {
+ p obj.Prog
+ set Dep
+ used Dep
+ soffset int32
+ size uint8
+ nop uint8
+ comp bool
+}
+
+func sched(ctxt *obj.Link, p0, pe *obj.Prog) {
+ var sch [NSCHED]Sch
+
+ /*
+ * build side structure
+ */
+ s := sch[:]
+ for p := p0; ; p = p.Link {
+ s[0].p = *p
+ markregused(ctxt, &s[0])
+ if p == pe {
+ break
+ }
+ s = s[1:]
+ }
+ se := s
+
+ for i := cap(sch) - cap(se); i >= 0; i-- {
+ s = sch[i:]
+ if s[0].p.Mark&DELAY == 0 {
+ continue
+ }
+ if -cap(s) < -cap(se) {
+ if !conflict(&s[0], &s[1]) {
+ continue
+ }
+ }
+
+ var t []Sch
+ var j int
+ for j = cap(sch) - cap(s) - 1; j >= 0; j-- {
+ t = sch[j:]
+ if t[0].comp {
+ if s[0].p.Mark&BRANCH != 0 {
+ goto no2
+ }
+ }
+ if t[0].p.Mark&DELAY != 0 {
+ if -cap(s) >= -cap(se) || conflict(&t[0], &s[1]) {
+ goto no2
+ }
+ }
+ for u := t[1:]; -cap(u) <= -cap(s); u = u[1:] {
+ if depend(ctxt, &u[0], &t[0]) {
+ goto no2
+ }
+ }
+ goto out2
+ no2:
+ }
+
+ if s[0].p.Mark&BRANCH != 0 {
+ s[0].nop = 1
+ }
+ continue
+
+ out2:
+ // t[0] is the instruction being moved to fill the delay
+ stmp := t[0]
+ copy(t[:i-j], t[1:i-j+1])
+ s[0] = stmp
+
+ if t[i-j-1].p.Mark&BRANCH != 0 {
+ // t[i-j] is being put into a branch delay slot
+ // combine its Spadj with the branch instruction
+ t[i-j-1].p.Spadj += t[i-j].p.Spadj
+ t[i-j].p.Spadj = 0
+ }
+
+ i--
+ }
+
+ /*
+ * put it all back
+ */
+ var p *obj.Prog
+ var q *obj.Prog
+ for s, p = sch[:], p0; -cap(s) <= -cap(se); s, p = s[1:], q {
+ q = p.Link
+ if q != s[0].p.Link {
+ *p = s[0].p
+ p.Link = q
+ }
+ for s[0].nop != 0 {
+ s[0].nop--
+ addnop(ctxt, p)
+ }
+ }
+}
+
+func markregused(ctxt *obj.Link, s *Sch) {
+ p := &s.p
+ s.comp = compound(ctxt, p)
+ s.nop = 0
+ if s.comp {
+ s.set.ireg |= 1 << (REGTMP - REG_R0)
+ s.used.ireg |= 1 << (REGTMP - REG_R0)
+ }
+
+ ar := 0 /* dest is really reference */
+ ad := 0 /* source/dest is really address */
+ ld := 0 /* opcode is load instruction */
+ sz := 20 /* size of load/store for overlap computation */
+
+ /*
+ * flags based on opcode
+ */
+ switch p.As {
+ case obj.ATEXT:
+ ctxt.Autosize = int32(p.To.Offset + 8)
+ ad = 1
+
+ case AJAL:
+ c := p.Reg
+ if c == 0 {
+ c = REGLINK
+ }
+ s.set.ireg |= 1 << uint(c-REG_R0)
+ ar = 1
+ ad = 1
+
+ case ABGEZAL,
+ ABLTZAL:
+ s.set.ireg |= 1 << (REGLINK - REG_R0)
+ fallthrough
+ case ABEQ,
+ ABGEZ,
+ ABGTZ,
+ ABLEZ,
+ ABLTZ,
+ ABNE:
+ ar = 1
+ ad = 1
+
+ case ABFPT,
+ ABFPF:
+ ad = 1
+ s.used.cc |= E_FCR
+
+ case ACMPEQD,
+ ACMPEQF,
+ ACMPGED,
+ ACMPGEF,
+ ACMPGTD,
+ ACMPGTF:
+ ar = 1
+ s.set.cc |= E_FCR
+ p.Mark |= FCMP
+
+ case AJMP:
+ ar = 1
+ ad = 1
+
+ case AMOVB,
+ AMOVBU:
+ sz = 1
+ ld = 1
+
+ case AMOVH,
+ AMOVHU:
+ sz = 2
+ ld = 1
+
+ case AMOVF,
+ AMOVW,
+ AMOVWL,
+ AMOVWR:
+ sz = 4
+ ld = 1
+
+ case AMOVD,
+ AMOVV,
+ AMOVVL,
+ AMOVVR:
+ sz = 8
+ ld = 1
+
+ case ADIV,
+ ADIVU,
+ AMUL,
+ AMULU,
+ AREM,
+ AREMU,
+ ADIVV,
+ ADIVVU,
+ AMULV,
+ AMULVU,
+ AREMV,
+ AREMVU:
+ s.set.cc = E_HILO
+ fallthrough
+ case AADD,
+ AADDU,
+ AADDV,
+ AADDVU,
+ AAND,
+ ANOR,
+ AOR,
+ ASGT,
+ ASGTU,
+ ASLL,
+ ASRA,
+ ASRL,
+ ASLLV,
+ ASRAV,
+ ASRLV,
+ ASUB,
+ ASUBU,
+ ASUBV,
+ ASUBVU,
+ AXOR,
+
+ AADDD,
+ AADDF,
+ AADDW,
+ ASUBD,
+ ASUBF,
+ ASUBW,
+ AMULF,
+ AMULD,
+ AMULW,
+ ADIVF,
+ ADIVD,
+ ADIVW:
+ if p.Reg == 0 {
+ if p.To.Type == obj.TYPE_REG {
+ p.Reg = p.To.Reg
+ }
+ //if(p->reg == NREG)
+ // print("botch %P\n", p);
+ }
+ }
+
+ /*
+ * flags based on 'to' field
+ */
+ c := int(p.To.Class)
+ if c == 0 {
+ c = aclass(ctxt, &p.To) + 1
+ p.To.Class = int8(c)
+ }
+ c--
+ switch c {
+ default:
+ fmt.Printf("unknown class %d %v\n", c, p)
+
+ case C_ZCON,
+ C_SCON,
+ C_ADD0CON,
+ C_AND0CON,
+ C_ADDCON,
+ C_ANDCON,
+ C_UCON,
+ C_LCON,
+ C_NONE,
+ C_SBRA,
+ C_LBRA,
+ C_ADDR,
+ C_TEXTSIZE:
+ break
+
+ case C_HI,
+ C_LO:
+ s.set.cc |= E_HILO
+
+ case C_FCREG:
+ s.set.cc |= E_FCR
+
+ case C_MREG:
+ s.set.cc |= E_MCR
+
+ case C_ZOREG,
+ C_SOREG,
+ C_LOREG:
+ c = int(p.To.Reg)
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ m := uint32(ANYMEM)
+ if c == REGSB {
+ m = E_MEMSB
+ }
+ if c == REGSP {
+ m = E_MEMSP
+ }
+
+ if ar != 0 {
+ s.used.cc |= m
+ } else {
+ s.set.cc |= m
+ }
+
+ case C_SACON,
+ C_LACON:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+
+ case C_SECON,
+ C_LECON:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+
+ case C_REG:
+ if ar != 0 {
+ s.used.ireg |= 1 << uint(p.To.Reg-REG_R0)
+ } else {
+ s.set.ireg |= 1 << uint(p.To.Reg-REG_R0)
+ }
+
+ case C_FREG:
+ if ar != 0 {
+ s.used.freg |= 1 << uint(p.To.Reg-REG_F0)
+ } else {
+ s.set.freg |= 1 << uint(p.To.Reg-REG_F0)
+ }
+ if ld != 0 && p.From.Type == obj.TYPE_REG {
+ p.Mark |= LOAD
+ }
+
+ case C_SAUTO,
+ C_LAUTO:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ if ar != 0 {
+ s.used.cc |= E_MEMSP
+ } else {
+ s.set.cc |= E_MEMSP
+ }
+
+ case C_SEXT,
+ C_LEXT:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.To)
+
+ if ar != 0 {
+ s.used.cc |= E_MEMSB
+ } else {
+ s.set.cc |= E_MEMSB
+ }
+ }
+
+ /*
+ * flags based on 'from' field
+ */
+ c = int(p.From.Class)
+ if c == 0 {
+ c = aclass(ctxt, &p.From) + 1
+ p.From.Class = int8(c)
+ }
+ c--
+ switch c {
+ default:
+ fmt.Printf("unknown class %d %v\n", c, p)
+
+ case C_ZCON,
+ C_SCON,
+ C_ADD0CON,
+ C_AND0CON,
+ C_ADDCON,
+ C_ANDCON,
+ C_UCON,
+ C_LCON,
+ C_NONE,
+ C_SBRA,
+ C_LBRA,
+ C_ADDR,
+ C_TEXTSIZE:
+ break
+
+ case C_HI,
+ C_LO:
+ s.used.cc |= E_HILO
+
+ case C_FCREG:
+ s.used.cc |= E_FCR
+
+ case C_MREG:
+ s.used.cc |= E_MCR
+
+ case C_ZOREG,
+ C_SOREG,
+ C_LOREG:
+ c = int(p.From.Reg)
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ m := uint32(ANYMEM)
+ if c == REGSB {
+ m = E_MEMSB
+ }
+ if c == REGSP {
+ m = E_MEMSP
+ }
+
+ s.used.cc |= m
+
+ case C_SACON,
+ C_LACON:
+ c = int(p.From.Reg)
+ if c == 0 {
+ c = REGSP
+ }
+ s.used.ireg |= 1 << uint(c-REG_R0)
+
+ case C_SECON,
+ C_LECON:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+
+ case C_REG:
+ s.used.ireg |= 1 << uint(p.From.Reg-REG_R0)
+
+ case C_FREG:
+ s.used.freg |= 1 << uint(p.From.Reg-REG_F0)
+ if ld != 0 && p.To.Type == obj.TYPE_REG {
+ p.Mark |= LOAD
+ }
+
+ case C_SAUTO,
+ C_LAUTO:
+ s.used.ireg |= 1 << (REGSP - REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ s.used.cc |= E_MEMSP
+
+ case C_SEXT:
+ case C_LEXT:
+ s.used.ireg |= 1 << (REGSB - REG_R0)
+ if ld != 0 {
+ p.Mark |= LOAD
+ }
+ if ad != 0 {
+ break
+ }
+ s.size = uint8(sz)
+ s.soffset = regoff(ctxt, &p.From)
+
+ s.used.cc |= E_MEMSB
+ }
+
+ c = int(p.Reg)
+ if c != 0 {
+ if REG_F0 <= c && c <= REG_F31 {
+ s.used.freg |= 1 << uint(c-REG_F0)
+ } else {
+ s.used.ireg |= 1 << uint(c-REG_R0)
+ }
+ }
+ s.set.ireg &^= (1 << (REGZERO - REG_R0)) /* R0 cant be set */
}
-func relinv(a int) int {
- switch a {
- case ABEQ:
- return ABNE
- case ABNE:
- return ABEQ
+/*
+ * test to see if 2 instrictions can be
+ * interchanged without changing semantics
+ */
+func depend(ctxt *obj.Link, sa, sb *Sch) bool {
+ if sa.set.ireg&(sb.set.ireg|sb.used.ireg) != 0 {
+ return true
+ }
+ if sb.set.ireg&sa.used.ireg != 0 {
+ return true
+ }
- case ABGE:
- return ABLT
- case ABLT:
- return ABGE
+ if sa.set.freg&(sb.set.freg|sb.used.freg) != 0 {
+ return true
+ }
+ if sb.set.freg&sa.used.freg != 0 {
+ return true
+ }
- case ABGT:
- return ABLE
- case ABLE:
- return ABGT
+ /*
+ * special case.
+ * loads from same address cannot pass.
+ * this is for hardware fifo's and the like
+ */
+ if sa.used.cc&sb.used.cc&E_MEM != 0 {
+ if sa.p.Reg == sb.p.Reg {
+ if regoff(ctxt, &sa.p.From) == regoff(ctxt, &sb.p.From) {
+ return true
+ }
+ }
+ }
+
+ x := (sa.set.cc & (sb.set.cc | sb.used.cc)) | (sb.set.cc & sa.used.cc)
+ if x != 0 {
+ /*
+ * allow SB and SP to pass each other.
+ * allow SB to pass SB iff doffsets are ok
+ * anything else conflicts
+ */
+ if x != E_MEMSP && x != E_MEMSB {
+ return true
+ }
+ x = sa.set.cc | sb.set.cc | sa.used.cc | sb.used.cc
+ if x&E_MEM != 0 {
+ return true
+ }
+ if offoverlap(sa, sb) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func offoverlap(sa, sb *Sch) bool {
+ if sa.soffset < sb.soffset {
+ if sa.soffset+int32(sa.size) > sb.soffset {
+ return true
+ }
+ return false
+ }
+ if sb.soffset+int32(sb.size) > sa.soffset {
+ return true
+ }
+ return false
+}
- case ABVC:
- return ABVS
- case ABVS:
- return ABVC
+/*
+ * test 2 adjacent instructions
+ * and find out if inserted instructions
+ * are desired to prevent stalls.
+ */
+func conflict(sa, sb *Sch) bool {
+ if sa.set.ireg&sb.used.ireg != 0 {
+ return true
+ }
+ if sa.set.freg&sb.used.freg != 0 {
+ return true
+ }
+ if sa.set.cc&sb.used.cc != 0 {
+ return true
}
+ return false
+}
- return 0
+func compound(ctxt *obj.Link, p *obj.Prog) bool {
+ o := oplook(ctxt, p)
+ if o.size != 4 {
+ return true
+ }
+ if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSB {
+ return true
+ }
+ return false
+}
+
+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 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:
@@ -822,7 +1350,7 @@ loop:
return
}
a = int(p.As)
- if a == ABR {
+ if a == AJMP {
q = p.Pcond
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
p.Mark |= FOLL
@@ -853,21 +1381,19 @@ loop:
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 {
+ if a == AJMP || a == ARET || a == ARFE {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
- b = relinv(a)
- if b == 0 {
+ if a != ABEQ && a != ABNE {
continue
}
@@ -888,10 +1414,13 @@ loop:
(*last).Link = r
*last = r
- if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if a == AJMP || a == ARET || a == ARFE {
return
}
- r.As = int16(b)
+ r.As = ABNE
+ if a == ABNE {
+ r.As = ABEQ
+ }
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
@@ -904,7 +1433,7 @@ loop:
}
}
- a = ABR
+ a = AJMP
q = ctxt.NewProg()
q.As = int16(a)
q.Lineno = p.Lineno
@@ -917,7 +1446,7 @@ loop:
p.Mark |= FOLL
(*last).Link = p
*last = p
- if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if a == AJMP || a == ARET || a == ARFE {
if p.Mark&NOSCHED != 0 {
p = p.Link
goto loop
@@ -927,7 +1456,7 @@ loop:
}
if p.Pcond != nil {
- if a != ABL && p.Link != nil {
+ if a != AJAL && p.Link != nil {
xfol(ctxt, p.Link, last)
p = p.Pcond
if p == nil || (p.Mark&FOLL != 0) {
@@ -941,12 +1470,12 @@ loop:
goto loop
}
-var Linkppc64 = obj.LinkArch{
+var Linkmips64 = obj.LinkArch{
ByteOrder: binary.BigEndian,
- Name: "ppc64",
- Thechar: '9',
+ Name: "mips64",
+ Thechar: '0',
Preprocess: preprocess,
- Assemble: span9,
+ Assemble: span0,
Follow: follow,
Progedit: progedit,
Minlc: 4,
@@ -954,12 +1483,12 @@ var Linkppc64 = obj.LinkArch{
Regsize: 8,
}
-var Linkppc64le = obj.LinkArch{
+var Linkmips64le = obj.LinkArch{
ByteOrder: binary.LittleEndian,
- Name: "ppc64le",
- Thechar: '9',
+ Name: "mips64le",
+ Thechar: '0',
Preprocess: preprocess,
- Assemble: span9,
+ Assemble: span0,
Follow: follow,
Progedit: progedit,
Minlc: 4,