]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/mips: add support for GOARCH=mips{,le}
authorVladimir Stefanovic <vladimir.stefanovic@imgtec.com>
Tue, 18 Oct 2016 21:50:37 +0000 (23:50 +0200)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 8 Nov 2016 17:46:35 +0000 (17:46 +0000)
Implements subset of MIPS32(r1) instruction set.

Change-Id: Iba017350f6c2763de05d4d1bc2f123e8eb76d0ff
Reviewed-on: https://go-review.googlesource.com/31475
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/arch/arch.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/mips/a.out.go
src/cmd/internal/obj/mips/anames.go
src/cmd/internal/obj/mips/asm0.go
src/cmd/internal/obj/mips/list0.go
src/cmd/internal/obj/mips/obj0.go
src/cmd/internal/obj/util.go

index 7766b020daa1729580f89760233391306c3910ee..fd2430561b2022347e4e1bfa6d4e1fc068134c4b 100644 (file)
@@ -415,7 +415,7 @@ func archMips64() *Arch {
        }
        for i, s := range mips.Anames {
                if obj.As(i) >= obj.A_ARCHSPECIFIC {
-                       instructions[s] = obj.As(i) + obj.ABaseMIPS64
+                       instructions[s] = obj.As(i) + obj.ABaseMIPS
                }
        }
        // Annoying alias.
index 7d8502a1ea0117f4ace8f10b25d4b0e7c9890cd8..f2874bafbcbb4d090c986094251f232e6d1d591b 100644 (file)
@@ -311,7 +311,7 @@ const (
        ABaseAMD64
        ABasePPC64
        ABaseARM64
-       ABaseMIPS64
+       ABaseMIPS
        ABaseS390X
 
        AllowedOpCodes = 1 << 10            // The number of opcodes available for any given architecture.
@@ -532,7 +532,7 @@ const (
        // R_ADDRARM64 relocates an adrp, add pair to compute the address of the
        // referenced symbol.
        R_ADDRARM64
-       // R_ADDRMIPS (only used on mips64) resolves to the low 16 bits of an external
+       // R_ADDRMIPS (only used on mips/mips64) resolves to the low 16 bits of an external
        // address, by encoding it into the instruction.
        R_ADDRMIPS
        // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
@@ -660,7 +660,7 @@ const (
        // TODO(mundaym): remove once variants can be serialized - see issue 14218.
        R_PCRELDBL
 
-       // R_ADDRMIPSU (only used on mips64) resolves to the sign-adjusted "upper" 16
+       // R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16
        // bits (bit 16-31) of an external address, by encoding it into the instruction.
        R_ADDRMIPSU
        // R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
index eab65dda51f5108953d2db3bf7acf5c84e37f173..f732ed5235348d98a3c1bece37d7f896ec67cfb9 100644 (file)
@@ -44,7 +44,7 @@ const (
 )
 
 const (
-       REG_R0 = obj.RBaseMIPS64 + iota
+       REG_R0 = obj.RBaseMIPS + iota
        REG_R1
        REG_R2
        REG_R3
@@ -217,6 +217,11 @@ const (
        NSCHED = 20
 )
 
+const (
+       Mips32 = 32
+       Mips64 = 64
+)
+
 const (
        C_NONE = iota
        C_REG
@@ -258,7 +263,7 @@ const (
 )
 
 const (
-       AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota
+       AABSD = obj.ABaseMIPS + obj.A_ARCHSPECIFIC + iota
        AABSF
        AABSW
        AADD
@@ -278,6 +283,12 @@ const (
        ABLTZAL
        ABNE
        ABREAK
+       ACLO
+       ACLZ
+       ACMOVF
+       ACMOVN
+       ACMOVT
+       ACMOVZ
        ACMPEQD
        ACMPEQF
        ACMPGED
@@ -290,6 +301,7 @@ const (
        ADIVU
        ADIVW
        AGOK
+       ALL
        ALUI
        AMOVB
        AMOVBU
@@ -319,9 +331,12 @@ const (
        AREM
        AREMU
        ARFE
+       ASC
        ASGT
        ASGTU
        ASLL
+       ASQRTD
+       ASQRTF
        ASRA
        ASRL
        ASUB
@@ -329,11 +344,14 @@ const (
        ASUBF
        ASUBU
        ASUBW
+       ASYNC
        ASYSCALL
+       ATEQ
        ATLBP
        ATLBR
        ATLBWI
        ATLBWR
+       ATNE
        AWORD
        AXOR
 
index c78480994979b9ce85487ff828d795105006bf80..8482a9efc8c8785070c2e25f58c65da58135ce64 100644 (file)
@@ -26,6 +26,12 @@ var Anames = []string{
        "BLTZAL",
        "BNE",
        "BREAK",
+       "CLO",
+       "CLZ",
+       "CMOVF",
+       "CMOVN",
+       "CMOVT",
+       "CMOVZ",
        "CMPEQD",
        "CMPEQF",
        "CMPGED",
@@ -38,6 +44,7 @@ var Anames = []string{
        "DIVU",
        "DIVW",
        "GOK",
+       "LL",
        "LUI",
        "MOVB",
        "MOVBU",
@@ -67,9 +74,12 @@ var Anames = []string{
        "REM",
        "REMU",
        "RFE",
+       "SC",
        "SGT",
        "SGTU",
        "SLL",
+       "SQRTD",
+       "SQRTF",
        "SRA",
        "SRL",
        "SUB",
@@ -77,11 +87,14 @@ var Anames = []string{
        "SUBF",
        "SUBU",
        "SUBW",
+       "SYNC",
        "SYSCALL",
+       "TEQ",
        "TLBP",
        "TLBR",
        "TLBWI",
        "TLBWR",
+       "TNE",
        "WORD",
        "XOR",
        "MOVV",
index bac4a709002d1ad07e9a1625afa0bfd5ae6f9641..c421deecb989840adc54bc8288d498f69d638cff 100644 (file)
@@ -39,7 +39,7 @@ import (
 // Instruction layout.
 
 const (
-       funcAlign = 8
+       mips64FuncAlign = 8
 )
 
 const (
@@ -54,270 +54,319 @@ type Optab struct {
        type_ int8
        size  int8
        param int16
+       mode  int
 }
 
 var optab = []Optab{
-       {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
-       {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0},
-
-       {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 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},
-
-       {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},
-
-       {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
-       {ASLL, C_REG, C_REG, C_REG, 9, 4, 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},
-
-       {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},
-
-       {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},
-
-       {AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
-       {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
-       {AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
-       {AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
-       {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB},
-       {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
-       {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
-       {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
-       {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
-       {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP},
-       {AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
-       {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
-       {AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
-       {AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO},
-       {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, 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},
-       {AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0},
-       {AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0},
-       {AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0},
-       {AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0},
-       {AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0},
-
-       {AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
-       {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
-       {AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
-       {AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
-       {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB},
-       {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
-       {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
-       {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
-       {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
-       {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP},
-       {AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
-       {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
-       {AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
-       {AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO},
-       {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, 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},
-       {AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0},
-       {AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0},
-       {AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0},
-       {AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0},
-       {AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 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, 52, 12, REGSB},
-       {AMOVV, C_LECON, C_NONE, C_REG, 52, 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_STCON, C_NONE, C_REG, 55, 8, 0},
-       {AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0},
-
-       {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, 12, REGSB},
-       {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB},
-       {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB},
-       {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
-       {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
-       {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP},
-       {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO},
-       {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO},
-       {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, 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, 12, REGSB},
-       {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB},
-       {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB},
-       {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
-       {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
-       {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP},
-       {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO},
-       {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO},
-       {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, 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_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},
+       {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0, Mips64},
+       {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0},
+
+       {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0, Mips64},
+       {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0, 0},
+       {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0, 0},
+       {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0, Mips64},
+
+       {ASUB, C_REG, C_REG, C_REG, 2, 4, 0, 0},
+       {ASUBV, C_REG, C_REG, C_REG, 2, 4, 0, Mips64},
+       {AADD, C_REG, C_REG, C_REG, 2, 4, 0, 0},
+       {AADDV, C_REG, C_REG, C_REG, 2, 4, 0, Mips64},
+       {AAND, C_REG, C_REG, C_REG, 2, 4, 0, 0},
+       {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0, 0},
+       {ASUBV, C_REG, C_NONE, C_REG, 2, 4, 0, Mips64},
+       {AADD, C_REG, C_NONE, C_REG, 2, 4, 0, 0},
+       {AADDV, C_REG, C_NONE, C_REG, 2, 4, 0, Mips64},
+       {AAND, C_REG, C_NONE, C_REG, 2, 4, 0, 0},
+       {ACMOVN, C_REG, C_REG, C_REG, 2, 4, 0, 0},
+
+       {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0},
+       {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0},
+       {ASLLV, C_REG, C_NONE, C_REG, 9, 4, 0, Mips64},
+       {ASLLV, C_REG, C_REG, C_REG, 9, 4, 0, Mips64},
+       {ACLO, C_REG, C_NONE, C_REG, 9, 4, 0, 0},
+
+       {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0, 0},
+       {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0, 0},
+       {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0, 0},
+       {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0},
+       {AMOVVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0},
+       {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0},
+
+       {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVVL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64},
+       {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0},
+       {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, Mips64},
+       {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, Mips64},
+       {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0},
+       {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0},
+       {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0},
+       {AMOVVL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, Mips64},
+       {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0},
+       {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, Mips64},
+       {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, Mips64},
+       {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0},
+       {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0},
+       {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0},
+       {AMOVVL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, Mips64},
+       {ASC, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0},
+
+       {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVVL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, Mips64},
+       {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0},
+       {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, Mips64},
+       {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, Mips64},
+       {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0},
+       {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0},
+       {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0},
+       {AMOVVL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, Mips64},
+       {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0},
+       {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, Mips64},
+       {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, Mips64},
+       {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0},
+       {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0},
+       {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0},
+       {AMOVVL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, Mips64},
+       {ALL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0},
+
+       {AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, Mips64},
+       {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, Mips64},
+       {AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, Mips64},
+       {AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, Mips64},
+       {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, Mips64},
+       {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0},
+       {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, Mips64},
+       {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, Mips64},
+       {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0},
+       {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0},
+       {AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0},
+       {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, Mips64},
+       {AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, Mips64},
+       {AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0},
+       {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0},
+       {ASC, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0},
+       {AMOVW, C_REG, C_NONE, C_ADDR, 50, 8, 0, Mips32},
+       {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVB, C_REG, C_NONE, C_ADDR, 50, 8, 0, Mips32},
+       {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 8, 0, Mips32},
+       {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0, 0},
+       {AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0, Mips64},
+       {AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0, Mips64},
+       {AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0, 0},
+       {AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0, 0},
+
+       {AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, Mips64},
+       {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, Mips64},
+       {AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, Mips64},
+       {AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, Mips64},
+       {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, Mips64},
+       {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0},
+       {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, Mips64},
+       {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, Mips64},
+       {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0},
+       {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0},
+       {AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0},
+       {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, Mips64},
+       {AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, Mips64},
+       {AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0},
+       {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0},
+       {AMOVW, C_ADDR, C_NONE, C_REG, 51, 8, 0, Mips32},
+       {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0, Mips64},
+       {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0, Mips64},
+       {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0, Mips64},
+       {AMOVB, C_ADDR, C_NONE, C_REG, 51, 8, 0, Mips32},
+       {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0, Mips64},
+       {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 8, 0, Mips32},
+       {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0, Mips64},
+       {AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0, 0},
+       {AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0, Mips64},
+       {AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0, Mips64},
+       {AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0, 0},
+       {AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0, 0},
+
+       {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB, Mips64},
+       {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB, Mips64},
+       {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP, 0},
+       {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP, Mips64},
+       {AMOVW, C_LECON, C_NONE, C_REG, 52, 8, REGSB, Mips32},
+       {AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB, Mips64},
+       {AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB, Mips64},
+
+       {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP, 0},
+       {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP, Mips64},
+       {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, 0},
+       {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, Mips64},
+       {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, 0},
+       {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, Mips64},
+       {AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0, 0},
+       {AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0, Mips64},
+
+       {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0, 0},
+       {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0, Mips64},
+       {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0, 0},
+       {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0, Mips64},
+
+       {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0, 0},
+       {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0, Mips64},
+       {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0, 0},
+       {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0, Mips64},
+       {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0, Mips64},
+       {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0, Mips64},
+
+       {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0, 0},
+       {AMUL, C_REG, C_REG, C_REG, 22, 4, 0, 0},
+       {AMULV, C_REG, C_REG, C_NONE, 22, 4, 0, Mips64},
+
+       {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0, 0},
+       {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, 0},
+       {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0, 0},
+       {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0, 0},
+
+       {AADDV, C_ADD0CON, C_REG, C_REG, 4, 4, 0, Mips64},
+       {AADDV, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, Mips64},
+       {AADDV, C_ANDCON, C_REG, C_REG, 10, 8, 0, Mips64},
+       {AADDV, C_ANDCON, C_NONE, C_REG, 10, 8, 0, Mips64},
+
+       {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0, 0},
+       {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0, 0},
+       {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0, 0},
+       {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0, 0},
+
+       {AADD, C_UCON, C_REG, C_REG, 25, 8, 0, 0},
+       {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0, 0},
+       {AADDV, C_UCON, C_REG, C_REG, 25, 8, 0, Mips64},
+       {AADDV, C_UCON, C_NONE, C_REG, 25, 8, 0, Mips64},
+       {AAND, C_UCON, C_REG, C_REG, 25, 8, 0, 0},
+       {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0, 0},
+
+       {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0, 0},
+       {AADDV, C_LCON, C_NONE, C_REG, 23, 12, 0, Mips64},
+       {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0, 0},
+       {AADD, C_LCON, C_REG, C_REG, 23, 12, 0, 0},
+       {AADDV, C_LCON, C_REG, C_REG, 23, 12, 0, Mips64},
+       {AAND, C_LCON, C_REG, C_REG, 23, 12, 0, 0},
+
+       {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0, 0},
+       {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0, 0},
+
+       {ASLLV, C_SCON, C_REG, C_REG, 16, 4, 0, Mips64},
+       {ASLLV, C_SCON, C_NONE, C_REG, 16, 4, 0, Mips64},
+
+       {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
+
+       {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0, 0},
+       {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0},
+       {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0},
+       {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0, 0},
+
+       {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0},
+       {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0},
+
+       {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO, 0},
+       {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK, 0},
+
+       {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, Mips64},
+       {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, Mips64},
+       {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, Mips64},
+       {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, Mips64},
+       {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0},
+       {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0},
+       {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, Mips64},
+       {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0},
+       {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0},
+
+       {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, Mips64},
+       {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, Mips64},
+       {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, Mips64},
+       {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, Mips64},
+       {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0},
+       {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0},
+       {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, Mips64},
+       {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0},
+       {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0},
+       {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 8, 0, Mips32},
+       {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0, Mips64},
+       {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 8, 0, Mips32},
+       {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0, Mips64},
+
+       {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, Mips64},
+       {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, Mips64},
+       {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0},
+       {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0},
+       {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0},
+       {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0},
+
+       {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, Mips64},
+       {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, Mips64},
+       {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0},
+       {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0},
+       {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, Mips64},
+       {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0},
+       {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0},
+       {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 8, 0, Mips32},
+       {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+       {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 8, 0, Mips32},
+       {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0, Mips64},
+
+       {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0, 0},
+       {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0, Mips64},
+       {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0, Mips64},
+
+       {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0, Mips64},
+       {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0, Mips64},
+
+       {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0, Mips64},
+       {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0, 0},
+       {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0, Mips64},
+
+       {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0},
+
+       {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0, 0},
+       {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0, Mips64},
+       {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0},
+       {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, Mips64},
+
+       {ATEQ, C_SCON, C_REG, C_REG, 15, 4, 0, 0},
+       {ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0},
+       {ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0},
+
+       {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, Mips64}, /* really CACHE instruction */
+       {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, Mips64},
+       {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, Mips64},
+       {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
+
+       {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
+       {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0},
+       {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0},
+       {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0, 0},
+       {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
+       {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0}, // same as AJMP
+       {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0}, // same as AJMP
+
+       {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
 }
 
 var oprange [ALAST & obj.AMask][]Optab
@@ -330,7 +379,7 @@ func span0(ctxt *obj.Link, cursym *obj.LSym) {
                return
        }
        ctxt.Cursym = cursym
-       ctxt.Autosize = int32(p.To.Offset + 8)
+       ctxt.Autosize = int32(p.To.Offset + ctxt.FixedFrameSize())
 
        if oprange[AOR&obj.AMask] == nil {
                buildop(ctxt)
@@ -417,8 +466,9 @@ func span0(ctxt *obj.Link, cursym *obj.LSym) {
 
                cursym.Size = c
        }
-
-       c += -c & (funcAlign - 1)
+       if ctxt.Mode&Mips64 != 0 {
+               c += -c & (mips64FuncAlign - 1)
+       }
        cursym.Size = c
 
        /*
@@ -503,7 +553,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        return C_LAUTO
 
                case obj.NAME_PARAM:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
                        if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
                                return C_SAUTO
                        }
@@ -567,7 +617,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
                        return C_LACON
 
                case obj.NAME_PARAM:
-                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+                       ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
                        if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
                                return C_SACON
                        }
@@ -653,7 +703,7 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
        c3 := &xcmp[a3]
        for i := range ops {
                op := &ops[i]
-               if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
+               if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && (ctxt.Mode&op.mode == op.mode) {
                        p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
                        return op
                }
@@ -824,18 +874,22 @@ func buildop(ctxt *obj.Link) {
                        opset(AABSD, r0)
                        opset(ATRUNCDW, r0)
                        opset(ATRUNCFW, r0)
-                       opset(ATRUNCDV, r0)
-                       opset(ATRUNCFV, r0)
-                       opset(AMOVVF, r0)
-                       opset(AMOVFV, r0)
+                       opset(ASQRTF, r0)
+                       opset(ASQRTD, r0)
+
+               case AMOVVF:
                        opset(AMOVVD, r0)
+                       opset(AMOVFV, r0)
                        opset(AMOVDV, r0)
+                       opset(ATRUNCDV, r0)
+                       opset(ATRUNCFV, r0)
 
                case AADD:
                        opset(ASGT, r0)
                        opset(ASGTU, r0)
                        opset(AADDU, r0)
-                       opset(AADDV, r0)
+
+               case AADDV:
                        opset(AADDVU, r0)
 
                case AADDF:
@@ -873,9 +927,10 @@ func buildop(ctxt *obj.Link) {
                        opset(ADIVU, r0)
                        opset(AMULU, r0)
                        opset(ADIV, r0)
+
+               case AMULV:
                        opset(ADIVV, r0)
                        opset(ADIVVU, r0)
-                       opset(AMULV, r0)
                        opset(AMULVU, r0)
                        opset(AREMV, r0)
                        opset(AREMVU, r0)
@@ -883,17 +938,20 @@ func buildop(ctxt *obj.Link) {
                case ASLL:
                        opset(ASRL, r0)
                        opset(ASRA, r0)
-                       opset(ASLLV, r0)
+
+               case ASLLV:
                        opset(ASRAV, r0)
                        opset(ASRLV, r0)
 
                case ASUB:
                        opset(ASUBU, r0)
-                       opset(ASUBV, r0)
-                       opset(ASUBVU, r0)
                        opset(ANOR, r0)
 
+               case ASUBV:
+                       opset(ASUBVU, r0)
+
                case ASYSCALL:
+                       opset(ASYNC, r0)
                        opset(ATLBP, r0)
                        opset(ATLBR, r0)
                        opset(ATLBWI, r0)
@@ -911,8 +969,9 @@ func buildop(ctxt *obj.Link) {
 
                case AMOVWL:
                        opset(AMOVWR, r0)
+
+               case AMOVVL:
                        opset(AMOVVR, r0)
-                       opset(AMOVVL, r0)
 
                case AMOVW,
                        AMOVD,
@@ -923,6 +982,8 @@ func buildop(ctxt *obj.Link) {
                        AJAL,
                        AJMP,
                        AMOVWU,
+                       ALL,
+                       ASC,
                        AWORD,
                        obj.ANOP,
                        obj.ATEXT,
@@ -933,6 +994,18 @@ func buildop(ctxt *obj.Link) {
                        obj.ADUFFZERO,
                        obj.ADUFFCOPY:
                        break
+
+               case ACMOVN:
+                       opset(ACMOVZ, r0)
+
+               case ACMOVT:
+                       opset(ACMOVF, r0)
+
+               case ACLO:
+                       opset(ACLZ, r0)
+
+               case ATEQ:
+                       opset(ATNE, r0)
                }
        }
 }
@@ -995,6 +1068,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
        o3 := uint32(0)
        o4 := uint32(0)
 
+       add := AADDU
+
+       if ctxt.Mode&Mips64 != 0 {
+               add = AADDVU
+       }
        switch o.type_ {
        default:
                ctxt.Diag("unknown type %d %v", o.type_)
@@ -1005,10 +1083,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 
        case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
                a := AOR
-               if p.As == AMOVW {
+               if p.As == AMOVW && ctxt.Mode&Mips64 != 0 {
                        a = AADDU // sign-extended to high 32 bits
                }
-               o1 = OP_RRR(oprrr(ctxt, a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
+               o1 = OP_RRR(oprrr(ctxt, a), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
 
        case 2: /* add/sub r1,[r2],r3 */
                r := int(p.Reg)
@@ -1025,7 +1103,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                if r == 0 {
                        r = int(o.param)
                }
-               a := AADDVU
+               a := add
                if o.a1 == C_ANDCON {
                        a = AOR
                }
@@ -1152,6 +1230,15 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                o1 = OP_SRR(opirr(ctxt, -ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
                o2 = OP_SRR(opirr(ctxt, -ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
 
+       case 15: /* teq $c r,r */
+               v := regoff(ctxt, &p.From)
+               r := int(p.Reg)
+               if r == 0 {
+                       r = REGZERO
+               }
+               /* only use 10 bits of trap code */
+               o1 = OP_IRR(opirr(ctxt, p.As), (uint32(v)&0x3FF)<<6, uint32(p.Reg), uint32(p.To.Reg))
+
        case 16: /* sll $c,[r1],r2 */
                v := regoff(ctxt, &p.From)
                r := int(p.Reg)
@@ -1166,6 +1253,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        o1 = OP_SRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg))
                }
 
+       case 17:
+               o1 = OP_RRR(oprrr(ctxt, p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
+
        case 18: /* jmp [r1],0(r2) */
                r := int(p.Reg)
                if r == 0 {
@@ -1196,8 +1286,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                }
                o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
 
-       case 22: /* mul r1,r2 */
-               o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
+       case 22: /* mul r1,r2 [r3]*/
+               if p.To.Reg != 0 {
+                       r := int(p.Reg)
+                       if r == 0 {
+                               r = int(p.To.Reg)
+                       }
+                       a := SP(3, 4) | 2 /* mul */
+                       o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
+               } else {
+                       o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
+               }
 
        case 23: /* add $lcon,r1,r2 ==> lu+or+add */
                v := regoff(ctxt, &p.From)
@@ -1230,7 +1329,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                if r == 0 {
                        r = int(o.param)
                }
-               o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
+               o3 = OP_RRR(oprrr(ctxt, add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
 
        case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
                v := regoff(ctxt, &p.From)
@@ -1245,7 +1344,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                switch o.size {
                case 12:
                        o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
-                       o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+                       o2 = OP_RRR(oprrr(ctxt, add), uint32(r), uint32(REGTMP), uint32(REGTMP))
                        o3 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
 
                case 4:
@@ -1265,7 +1364,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                switch o.size {
                case 12:
                        o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
-                       o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+                       o2 = OP_RRR(oprrr(ctxt, add), uint32(r), uint32(REGTMP), uint32(REGTMP))
                        o3 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
 
                case 4:
@@ -1306,7 +1405,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        r = int(o.param)
                }
                o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
-               o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+               o2 = OP_RRR(oprrr(ctxt, add), uint32(r), uint32(REGTMP), uint32(REGTMP))
                o3 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
 
        case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
@@ -1316,7 +1415,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                        r = int(o.param)
                }
                o1 = OP_IRR(opirr(ctxt, ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
-               o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+               o2 = OP_RRR(oprrr(ctxt, add), uint32(r), uint32(REGTMP), uint32(REGTMP))
                o3 = OP_IRR(opirr(ctxt, -p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
 
        case 37: /* movw r,mr */
@@ -1363,15 +1462,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel.Sym = p.To.Sym
                rel.Add = p.To.Offset
                rel.Type = obj.R_ADDRMIPSU
-               o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
-               o3 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+               o2 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
                rel2 := obj.Addrel(ctxt.Cursym)
-               rel2.Off = int32(ctxt.Pc + 8)
+               rel2.Off = int32(ctxt.Pc + 4)
                rel2.Siz = 4
                rel2.Sym = p.To.Sym
                rel2.Add = p.To.Offset
                rel2.Type = obj.R_ADDRMIPS
 
+               if o.size == 12 {
+                       o3 = o2
+                       o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
+                       rel2.Off += 4
+               }
+
        case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
                o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
                rel := obj.Addrel(ctxt.Cursym)
@@ -1380,15 +1484,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel.Sym = p.From.Sym
                rel.Add = p.From.Offset
                rel.Type = obj.R_ADDRMIPSU
-               o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
-               o3 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
+               o2 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
                rel2 := obj.Addrel(ctxt.Cursym)
-               rel2.Off = int32(ctxt.Pc + 8)
+               rel2.Off = int32(ctxt.Pc + 4)
                rel2.Siz = 4
                rel2.Sym = p.From.Sym
                rel2.Add = p.From.Offset
                rel2.Type = obj.R_ADDRMIPS
 
+               if o.size == 12 {
+                       o3 = o2
+                       o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
+                       rel2.Off += 4
+               }
+
        case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
                o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
                rel := obj.Addrel(ctxt.Cursym)
@@ -1397,15 +1506,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
                rel.Sym = p.From.Sym
                rel.Add = p.From.Offset
                rel.Type = obj.R_ADDRMIPSU
-               o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
-               o3 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
+               o2 = OP_IRR(opirr(ctxt, add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
                rel2 := obj.Addrel(ctxt.Cursym)
-               rel2.Off = int32(ctxt.Pc + 8)
+               rel2.Off = int32(ctxt.Pc + 4)
                rel2.Siz = 4
                rel2.Sym = p.From.Sym
                rel2.Add = p.From.Offset
                rel2.Type = obj.R_ADDRMIPS
 
+               if o.size == 12 {
+                       o3 = o2
+                       o2 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
+                       rel2.Off += 4
+               }
+
        case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
                // clobbers R3 !
                // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
@@ -1432,7 +1546,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
        case 55: /* mov $tlsvar, r ==> rdhwr + add */
                // clobbers R3 !
                o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
-               o2 = OP_IRR(opirr(ctxt, AADDVU), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
+               o2 = OP_IRR(opirr(ctxt, add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
                rel := obj.Addrel(ctxt.Cursym)
                rel.Off = int32(ctxt.Pc + 4)
                rel.Siz = 4
@@ -1609,6 +1723,27 @@ func oprrr(ctxt *obj.Link, a obj.As) uint32 {
                return FPF(7, 6)
        case ACMPGED:
                return FPD(7, 6)
+
+       case ASQRTF:
+               return FPF(0, 4)
+       case ASQRTD:
+               return FPD(0, 4)
+
+       case ASYNC:
+               return OP(1, 7)
+
+       case ACMOVN:
+               return OP(1, 3)
+       case ACMOVZ:
+               return OP(1, 2)
+       case ACMOVT:
+               return OP(0, 1) | (1 << 16)
+       case ACMOVF:
+               return OP(0, 1) | (0 << 16)
+       case ACLO:
+               return SP(3, 4) | OP(4, 1)
+       case ACLZ:
+               return SP(3, 4) | OP(4, 0)
        }
 
        if a < 0 {
@@ -1761,6 +1896,15 @@ func opirr(ctxt *obj.Link, a obj.As) uint32 {
                return OP(7, 6)
        case -ASRAV:
                return OP(7, 7)
+
+       case ATEQ:
+               return OP(6, 4)
+       case ATNE:
+               return OP(6, 6)
+       case -ALL:
+               return SP(6, 0)
+       case ASC:
+               return SP(7, 0)
        }
 
        if a < 0 {
index 28881e845da6bfc1ef9386f79b48d5e6a0a1e18a..4dd5e80ba1fbf499571e50f874abfd08695d310f 100644 (file)
@@ -35,8 +35,8 @@ import (
 )
 
 func init() {
-       obj.RegisterRegister(obj.RBaseMIPS64, REG_LAST&^1023+1024, Rconv)
-       obj.RegisterOpcode(obj.ABaseMIPS64, Anames)
+       obj.RegisterRegister(obj.RBaseMIPS, REG_LAST+1, Rconv)
+       obj.RegisterOpcode(obj.ABaseMIPS, Anames)
 }
 
 func Rconv(r int) string {
@@ -70,7 +70,7 @@ func Rconv(r int) string {
                return "LO"
        }
 
-       return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64)
+       return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS)
 }
 
 func DRconv(a int) string {
index 651da239554c3b422c661d7a024cb0a8ab060d3b..221fd428a32f2b2540fb0bb78240575e9167d095 100644 (file)
@@ -37,6 +37,18 @@ import (
 )
 
 func progedit(ctxt *obj.Link, p *obj.Prog) {
+       // Maintain information about code generation mode.
+       if ctxt.Mode == 0 {
+               switch ctxt.Arch.Family {
+               default:
+                       ctxt.Diag("unsupported arch family")
+               case sys.MIPS:
+                       ctxt.Mode = Mips32
+               case sys.MIPS64:
+                       ctxt.Mode = Mips64
+               }
+       }
+
        p.From.Class = 0
        p.To.Class = 0
 
@@ -59,7 +71,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
                        f32 := float32(p.From.Val.(float64))
                        i32 := math.Float32bits(f32)
                        if i32 == 0 {
-                               p.As = AMOVV
+                               p.As = AMOVW
                                p.From.Type = obj.TYPE_REG
                                p.From.Reg = REGZERO
                                break
@@ -76,7 +88,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
        case AMOVD:
                if p.From.Type == obj.TYPE_FCONST {
                        i64 := math.Float64bits(p.From.Val.(float64))
-                       if i64 == 0 {
+                       if i64 == 0 && ctxt.Mode&Mips64 != 0 {
                                p.As = AMOVV
                                p.From.Type = obj.TYPE_REG
                                p.From.Reg = REGZERO
@@ -271,6 +283,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                }
        }
 
+       var mov, add obj.As
+       if ctxt.Mode&Mips64 != 0 {
+               add = AADDV
+               mov = AMOVV
+       } else {
+               add = AADDU
+               mov = AMOVW
+       }
+
        autosize := int32(0)
        var p1 *obj.Prog
        var p2 *obj.Prog
@@ -278,13 +299,14 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                o := p.As
                switch o {
                case obj.ATEXT:
-                       autosize = int32(textstksiz + 8)
-                       if (p.Mark&LEAF != 0) && autosize <= 8 {
+                       autosize = int32(textstksiz + ctxt.FixedFrameSize())
+                       if (p.Mark&LEAF != 0) && autosize <= int32(ctxt.FixedFrameSize()) {
                                autosize = 0
-                       } else if autosize&4 != 0 {
+                       } else if autosize&4 != 0 && ctxt.Mode&Mips64 != 0 {
                                autosize += 4
                        }
-                       p.To.Offset = int64(autosize) - 8
+
+                       p.To.Offset = int64(autosize) - ctxt.FixedFrameSize()
 
                        if p.From3.Offset&obj.NOSPLIT == 0 {
                                p = stacksplit(ctxt, p, autosize) // emit split check
@@ -299,7 +321,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                // during the execution of the function prologue, the traceback
                                // code will not see a half-updated stack frame.
                                q = obj.Appendp(ctxt, q)
-                               q.As = AMOVV
+                               q.As = mov
                                q.Lineno = p.Lineno
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REGLINK
@@ -308,7 +330,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                q.To.Reg = REGSP
 
                                q = obj.Appendp(ctxt, q)
-                               q.As = AADDV
+                               q.As = add
                                q.Lineno = p.Lineno
                                q.From.Type = obj.TYPE_CONST
                                q.From.Offset = int64(-autosize)
@@ -333,13 +355,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                        if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
                                // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
                                //
-                               //      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)
+                               //      MOV     g_panic(g), R1
+                               //      BEQ     R1, end
+                               //      MOV     panic_argp(R1), R2
+                               //      ADD     $(autosize+FIXED_FRAME), R29, R3
+                               //      BNE     R2, R3, end
+                               //      ADD     $FIXED_FRAME, R29, R2
+                               //      MOV     R2, panic_argp(R1)
                                // end:
                                //      NOP
                                //
@@ -348,7 +370,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 
                                q = obj.Appendp(ctxt, q)
 
-                               q.As = AMOVV
+                               q.As = mov
                                q.From.Type = obj.TYPE_MEM
                                q.From.Reg = REGG
                                q.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic
@@ -364,7 +386,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                p1 = q
 
                                q = obj.Appendp(ctxt, q)
-                               q.As = AMOVV
+                               q.As = mov
                                q.From.Type = obj.TYPE_MEM
                                q.From.Reg = REG_R1
                                q.From.Offset = 0 // Panic.argp
@@ -372,9 +394,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                q.To.Reg = REG_R2
 
                                q = obj.Appendp(ctxt, q)
-                               q.As = AADDV
+                               q.As = add
                                q.From.Type = obj.TYPE_CONST
-                               q.From.Offset = int64(autosize) + 8
+                               q.From.Offset = int64(autosize) + ctxt.FixedFrameSize()
                                q.Reg = REGSP
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R3
@@ -389,15 +411,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                p2 = q
 
                                q = obj.Appendp(ctxt, q)
-                               q.As = AADDV
+                               q.As = add
                                q.From.Type = obj.TYPE_CONST
-                               q.From.Offset = 8
+                               q.From.Offset = ctxt.FixedFrameSize()
                                q.Reg = REGSP
                                q.To.Type = obj.TYPE_REG
                                q.To.Reg = REG_R2
 
                                q = obj.Appendp(ctxt, q)
-                               q.As = AMOVV
+                               q.As = mov
                                q.From.Type = obj.TYPE_REG
                                q.From.Reg = REG_R2
                                q.To.Type = obj.TYPE_MEM
@@ -438,7 +460,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                        break
                                }
 
-                               p.As = AADDV
+                               p.As = add
                                p.From.Type = obj.TYPE_CONST
                                p.From.Offset = int64(autosize)
                                p.To.Type = obj.TYPE_REG
@@ -459,7 +481,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                break
                        }
 
-                       p.As = AMOVV
+                       p.As = mov
                        p.From.Type = obj.TYPE_MEM
                        p.From.Offset = 0
                        p.From.Reg = REGSP
@@ -471,7 +493,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 
                        if autosize != 0 {
                                q = ctxt.NewProg()
-                               q.As = AADDV
+                               q.As = add
                                q.Lineno = p.Lineno
                                q.From.Type = obj.TYPE_CONST
                                q.From.Offset = int64(autosize)
@@ -501,7 +523,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                        q1.Link = q.Link
                        q.Link = q1
 
-               case AADDV,
+               case AADD,
+                       AADDU,
+                       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)
@@ -564,10 +588,27 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 }
 
 func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
-       // MOVV g_stackguard(g), R1
+       // Leaf function with no frame is effectively NOSPLIT.
+       if framesize == 0 {
+               return p
+       }
+
+       var mov, add, sub obj.As
+
+       if ctxt.Mode&Mips64 != 0 {
+               add = AADDV
+               mov = AMOVV
+               sub = ASUBVU
+       } else {
+               add = AADDU
+               mov = AMOVW
+               sub = ASUBU
+       }
+
+       // MOV  g_stackguard(g), R1
        p = obj.Appendp(ctxt, p)
 
-       p.As = AMOVV
+       p.As = mov
        p.From.Type = obj.TYPE_MEM
        p.From.Reg = REGG
        p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
@@ -591,11 +632,11 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
                p.To.Reg = REG_R1
        } else if framesize <= obj.StackBig {
                // large stack: SP-framesize < stackguard-StackSmall
-               //      ADDV    $-framesize, SP, R2
+               //      ADD     $-framesize, SP, R2
                //      SGTU    R2, stackguard, R1
                p = obj.Appendp(ctxt, p)
 
-               p.As = AADDV
+               p.As = add
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(-framesize)
                p.Reg = REGSP
@@ -619,15 +660,15 @@ 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 R1
-               //      MOVV    $StackPreempt, R2
+               //      MOV     $StackPreempt, R2
                //      BEQ     R1, R2, label-of-call-to-morestack
-               //      ADDV    $StackGuard, SP, R2
-               //      SUBVU   R1, R2
-               //      MOVV    $(framesize+(StackGuard-StackSmall)), R1
+               //      ADD     $StackGuard, SP, R2
+               //      SUB     R1, R2
+               //      MOV     $(framesize+(StackGuard-StackSmall)), R1
                //      SGTU    R2, R1, R1
                p = obj.Appendp(ctxt, p)
 
-               p.As = AMOVV
+               p.As = mov
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = obj.StackPreempt
                p.To.Type = obj.TYPE_REG
@@ -643,7 +684,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
                p.Mark |= BRANCH
 
                p = obj.Appendp(ctxt, p)
-               p.As = AADDV
+               p.As = add
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = obj.StackGuard
                p.Reg = REGSP
@@ -651,14 +692,14 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
                p.To.Reg = REG_R2
 
                p = obj.Appendp(ctxt, p)
-               p.As = ASUBVU
+               p.As = sub
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REG_R1
                p.To.Type = obj.TYPE_REG
                p.To.Reg = REG_R2
 
                p = obj.Appendp(ctxt, p)
-               p.As = AMOVV
+               p.As = mov
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
                p.To.Type = obj.TYPE_REG
@@ -683,10 +724,10 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
        p.To.Type = obj.TYPE_BRANCH
        p.Mark |= BRANCH
 
-       // MOVV LINK, R3
+       // MOV  LINK, R3
        p = obj.Appendp(ctxt, p)
 
-       p.As = AMOVV
+       p.As = mov
        p.From.Type = obj.TYPE_REG
        p.From.Reg = REGLINK
        p.To.Type = obj.TYPE_REG
@@ -1494,3 +1535,19 @@ var Linkmips64le = obj.LinkArch{
        Follow:     follow,
        Progedit:   progedit,
 }
+
+var Linkmips = obj.LinkArch{
+       Arch:       sys.ArchMIPS,
+       Preprocess: preprocess,
+       Assemble:   span0,
+       Follow:     follow,
+       Progedit:   progedit,
+}
+
+var Linkmipsle = obj.LinkArch{
+       Arch:       sys.ArchMIPSLE,
+       Preprocess: preprocess,
+       Assemble:   span0,
+       Follow:     follow,
+       Progedit:   progedit,
+}
index 9f1c6f08c79bf091a04c861f3dc101e1f2fc25d4..bc5d1c5d5a1552a4143915e984490c4ca2144b48 100644 (file)
@@ -384,13 +384,13 @@ var regSpace []regSet
 const (
        // Because of masking operations in the encodings, each register
        // space should start at 0 modulo some power of 2.
-       RBase386    = 1 * 1024
-       RBaseAMD64  = 2 * 1024
-       RBaseARM    = 3 * 1024
-       RBasePPC64  = 4 * 1024  // range [4k, 8k)
-       RBaseARM64  = 8 * 1024  // range [8k, 13k)
-       RBaseMIPS64 = 13 * 1024 // range [13k, 14k)
-       RBaseS390X  = 14 * 1024 // range [14k, 15k)
+       RBase386   = 1 * 1024
+       RBaseAMD64 = 2 * 1024
+       RBaseARM   = 3 * 1024
+       RBasePPC64 = 4 * 1024  // range [4k, 8k)
+       RBaseARM64 = 8 * 1024  // range [8k, 13k)
+       RBaseMIPS  = 13 * 1024 // range [13k, 14k)
+       RBaseS390X = 14 * 1024 // range [14k, 15k)
 )
 
 // RegisterRegister binds a pretty-printer (Rconv) for register