]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: added support for mips64{,le}
authorYao Zhang <lunaria21@gmail.com>
Thu, 10 Sep 2015 15:33:09 +0000 (11:33 -0400)
committerMinux Ma <minux@golang.org>
Thu, 12 Nov 2015 04:44:20 +0000 (04:44 +0000)
It is based on ppc64 compiler.

Change-Id: I15a101df05f2919ba5292136957ba0009227d067
Reviewed-on: https://go-review.googlesource.com/14445
Reviewed-by: Minux Ma <minux@golang.org>
14 files changed:
src/cmd/compile/internal/gc/cgen.go
src/cmd/compile/internal/gc/gsubr.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/reg.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/mips64/cgen.go
src/cmd/compile/internal/mips64/galign.go
src/cmd/compile/internal/mips64/ggen.go
src/cmd/compile/internal/mips64/gsubr.go
src/cmd/compile/internal/mips64/opt.go [deleted file]
src/cmd/compile/internal/mips64/peep.go
src/cmd/compile/internal/mips64/prog.go
src/cmd/compile/internal/mips64/reg.go
src/cmd/compile/main.go

index cbb84f9da8ac183e342baac21c3e18bd9dffaed2..42b7792fb2089f9ab9e440844151aba94dcfdfaa 100644 (file)
@@ -251,7 +251,7 @@ func cgen_wb(n, res *Node, wb bool) {
                return
        }
 
-       if Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+       if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
                // if both are addressable, move
                if n.Addable {
                        if n.Op == OREGISTER || res.Op == OREGISTER {
@@ -751,14 +751,14 @@ abop: // asymmetric binary
                Regalloc(&n1, nl.Type, res)
                Cgen(nl, &n1)
 
-               if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
+               if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
                        n2 = *nr
                } else {
                        Regalloc(&n2, nr.Type, nil)
                        Cgen(nr, &n2)
                }
        } else {
-               if Smallintconst(nr) && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
+               if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm
                        n2 = *nr
                } else {
                        Regalloc(&n2, nr.Type, res)
@@ -1829,8 +1829,8 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
                        // but they don't support direct generation of a bool value yet.
                        // We can fix that as we go.
                        switch Ctxt.Arch.Thechar {
-                       case '5', '7', '9':
-                               Fatalf("genval 5g, 7g, 9g ONAMES not fully implemented")
+                       case '0', '5', '7', '9':
+                               Fatalf("genval 0g, 5g, 7g, 9g ONAMES not fully implemented")
                        }
                        Cgen(n, res)
                        if !wantTrue {
@@ -1839,7 +1839,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
                        return
                }
 
-               if n.Addable && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
+               if n.Addable && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
                        // no need for a temporary
                        bgenNonZero(n, nil, wantTrue, likely, to)
                        return
@@ -2023,7 +2023,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
                Cgen(nl, &n1)
                nl = &n1
 
-               if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
+               if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' {
                        Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
                        bins(nr.Type, res, op, likely, to)
                        return
@@ -2048,6 +2048,13 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
                op = Brrev(op)
        }
 
+       // MIPS does not have CMP instruction
+       if Ctxt.Arch.Thechar == '0' {
+               p := Thearch.Ginscmp(op, nr.Type, l, r, likely)
+               Patch(p, to)
+               return
+       }
+
        // Do the comparison.
        Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), l, r)
 
@@ -2133,6 +2140,15 @@ func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
        if !wantTrue {
                op = OEQ
        }
+
+       // MIPS does not have CMP instruction
+       if Thearch.Thechar == '0' {
+               p := Gbranch(Thearch.Optoas(op, n.Type), n.Type, likely)
+               Naddr(&p.From, n)
+               Patch(p, to)
+               return
+       }
+
        var zero Node
        Nodconst(&zero, n.Type, 0)
        Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
@@ -2597,7 +2613,7 @@ func cgen_div(op Op, nl *Node, nr *Node, res *Node) {
        // in peep and optoas in order to enable this.
        // TODO(rsc): ppc64 needs to support the relevant instructions
        // in peep and optoas in order to enable this.
-       if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+       if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
                goto longdiv
        }
        w = int(nl.Type.Width * 8)
index 6b11ed2be8cd320982d11d9b8d008ac569230676..ba2c601b7fa29ff8b859e1e9e5612e50e1c1df45 100644 (file)
@@ -83,7 +83,7 @@ func Gbranch(as int, t *Type, likely int) *obj.Prog {
        p := Prog(as)
        p.To.Type = obj.TYPE_BRANCH
        p.To.Val = nil
-       if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' {
+       if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' && Thearch.Thechar != '0' {
                p.From.Type = obj.TYPE_CONST
                if likely > 0 {
                        p.From.Offset = 1
@@ -438,7 +438,7 @@ func Naddr(a *obj.Addr, n *Node) {
        case OADDR:
                Naddr(a, n.Left)
                a.Etype = uint8(Tptr)
-               if Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
+               if Thearch.Thechar != '0' && Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
                        a.Width = int64(Widthptr)
                }
                if a.Type != obj.TYPE_MEM {
index 015d2fd47ed219cdbbb331238f59863ed780e31f..a40738375d90c045de6f94e496fdbfb5d76733cc 100644 (file)
@@ -282,7 +282,7 @@ func allocauto(ptxt *obj.Prog) {
                if haspointers(n.Type) {
                        stkptrsize = Stksize
                }
-               if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+               if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
                        Stksize = Rnd(Stksize, int64(Widthptr))
                }
                if Stksize >= 1<<31 {
@@ -319,7 +319,7 @@ func Cgen_checknil(n *Node) {
                Fatalf("bad checknil")
        }
 
-       if ((Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
+       if ((Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
                var reg Node
                Regalloc(&reg, Types[Tptr], n)
                Cgen(n, &reg)
index b4ef993173be2269ffa2e6658ae6321b8a600635..f575094389cf71569b03d12f0308cf1bf407bbe2 100644 (file)
@@ -249,7 +249,7 @@ func addmove(r *Flow, bn int, rn int, f int) {
        p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)]))
 
        // TODO(rsc): Remove special case here.
-       if (Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
+       if (Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
                p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8]))
        }
        p1.From.Type = obj.TYPE_REG
@@ -302,7 +302,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
                // TODO(rsc): Remove special case here.
        case obj.TYPE_ADDR:
                var bit Bits
-               if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+               if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
                        goto memcase
                }
                a.Type = obj.TYPE_MEM
index a2bdbdc1ce499148b8ea80d3ddadad5325c741a5..9051be0eebced915cbdfa90a7bf85c14ad600243 100644 (file)
@@ -3290,7 +3290,7 @@ func samecheap(a *Node, b *Node) bool {
 }
 
 func walkrotate(np **Node) {
-       if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+       if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
                return
        }
 
@@ -3418,7 +3418,7 @@ func walkdiv(np **Node, init **NodeList) {
        // if >= 0, nr is 1<<pow // 1 if nr is negative.
 
        // TODO(minux)
-       if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+       if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
                return
        }
 
index 4f3092c9ef4789cd24032581be9cfcd952b66e54..434bfc73cbe689879ad4b511696628227430d1ff 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
 )
 
 func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
@@ -23,16 +23,16 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
                gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
 
        case 1:
-               op = ppc64.AMOVBU
+               op = mips.AMOVB
 
        case 2:
-               op = ppc64.AMOVHU
+               op = mips.AMOVH
 
        case 4:
-               op = ppc64.AMOVWZU // there is no lwau, only lwaux
+               op = mips.AMOVW
 
        case 8:
-               op = ppc64.AMOVDU
+               op = mips.AMOVV
        }
 
        if w%int64(align) != 0 {
@@ -53,7 +53,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
        if n.Ullman >= res.Ullman {
                gc.Agenr(n, &dst, res) // temporarily use dst
                gc.Regalloc(&src, gc.Types[gc.Tptr], nil)
-               gins(ppc64.AMOVD, &dst, &src)
+               gins(mips.AMOVV, &dst, &src)
                if res.Op == gc.ONAME {
                        gc.Gvardef(res)
                }
@@ -76,28 +76,28 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
        if dir < 0 {
                if c >= 4 {
                        gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
-                       gins(ppc64.AMOVD, &src, &nend)
+                       gins(mips.AMOVV, &src, &nend)
                }
 
-               p := gins(ppc64.AADD, nil, &src)
+               p := gins(mips.AADDV, nil, &src)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = w
 
-               p = gins(ppc64.AADD, nil, &dst)
+               p = gins(mips.AADDV, nil, &dst)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = w
        } else {
-               p := gins(ppc64.AADD, nil, &src)
+               p := gins(mips.AADDV, nil, &src)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(-dir)
 
-               p = gins(ppc64.AADD, nil, &dst)
+               p = gins(mips.AADDV, nil, &dst)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(-dir)
 
                if c >= 4 {
                        gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
-                       p := gins(ppc64.AMOVD, &src, &nend)
+                       p := gins(mips.AMOVV, &src, &nend)
                        p.From.Type = obj.TYPE_ADDR
                        p.From.Offset = w
                }
@@ -111,35 +111,43 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
                p.From.Offset = int64(dir)
                ploop := p
 
+               p = gins(mips.AADDV, nil, &src)
+               p.From.Type = obj.TYPE_CONST
+               p.From.Offset = int64(dir)
+
                p = gins(op, &tmp, &dst)
                p.To.Type = obj.TYPE_MEM
                p.To.Offset = int64(dir)
 
-               p = gins(ppc64.ACMP, &src, &nend)
+               p = gins(mips.AADDV, nil, &dst)
+               p.From.Type = obj.TYPE_CONST
+               p.From.Offset = int64(dir)
 
-               gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), ploop)
+               gc.Patch(ginsbranch(mips.ABNE, nil, &src, &nend, 0), ploop)
                gc.Regfree(&nend)
        } else {
-               // TODO(austin): Instead of generating ADD $-8,R8; ADD
-               // $-8,R7; n*(MOVDU 8(R8),R9; MOVDU R9,8(R7);) just
-               // generate the offsets directly and eliminate the
-               // ADDs.  That will produce shorter, more
+               // TODO: Instead of generating ADDV $-8,R8; ADDV
+               // $-8,R7; n*(MOVV 8(R8),R9; ADDV $8,R8; MOVV R9,8(R7);
+               // ADDV $8,R7;) just generate the offsets directly and
+               // eliminate the ADDs.  That will produce shorter, more
                // pipeline-able code.
                var p *obj.Prog
-               for {
-                       tmp14 := c
-                       c--
-                       if tmp14 <= 0 {
-                               break
-                       }
-
+               for ; c > 0; c-- {
                        p = gins(op, &src, &tmp)
                        p.From.Type = obj.TYPE_MEM
                        p.From.Offset = int64(dir)
 
+                       p = gins(mips.AADDV, nil, &src)
+                       p.From.Type = obj.TYPE_CONST
+                       p.From.Offset = int64(dir)
+
                        p = gins(op, &tmp, &dst)
                        p.To.Type = obj.TYPE_MEM
                        p.To.Offset = int64(dir)
+
+                       p = gins(mips.AADDV, nil, &dst)
+                       p.From.Type = obj.TYPE_CONST
+                       p.From.Offset = int64(dir)
                }
        }
 
index 16509da8fe1c9ee4439147ecd83faac0a487143c..00ffe17016a5bd7b696baee4a195ffd7e30d1fcd 100644 (file)
@@ -2,27 +2,27 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
 )
 
-var thechar int = '9'
+var thechar int = '0'
 
-var thestring string = "ppc64"
+var thestring string = "mips64"
 
 var thelinkarch *obj.LinkArch
 
 func linkarchinit() {
        thestring = obj.Getgoarch()
        gc.Thearch.Thestring = thestring
-       if thestring == "ppc64le" {
-               thelinkarch = &ppc64.Linkppc64le
+       if thestring == "mips64le" {
+               thelinkarch = &mips.Linkmips64le
        } else {
-               thelinkarch = &ppc64.Linkppc64
+               thelinkarch = &mips.Linkmips64
        }
        gc.Thearch.Thelinkarch = thelinkarch
 }
@@ -50,15 +50,15 @@ func Main() {
        gc.Thearch.Thestring = thestring
        gc.Thearch.Thelinkarch = thelinkarch
        gc.Thearch.Typedefs = typedefs
-       gc.Thearch.REGSP = ppc64.REGSP
-       gc.Thearch.REGCTXT = ppc64.REGCTXT
-       gc.Thearch.REGCALLX = ppc64.REG_R3
-       gc.Thearch.REGCALLX2 = ppc64.REG_R4
-       gc.Thearch.REGRETURN = ppc64.REG_R3
-       gc.Thearch.REGMIN = ppc64.REG_R0
-       gc.Thearch.REGMAX = ppc64.REG_R31
-       gc.Thearch.FREGMIN = ppc64.REG_F0
-       gc.Thearch.FREGMAX = ppc64.REG_F31
+       gc.Thearch.REGSP = mips.REGSP
+       gc.Thearch.REGCTXT = mips.REGCTXT
+       gc.Thearch.REGCALLX = mips.REG_R1
+       gc.Thearch.REGCALLX2 = mips.REG_R2
+       gc.Thearch.REGRETURN = mips.REGRET
+       gc.Thearch.REGMIN = mips.REG_R0
+       gc.Thearch.REGMAX = mips.REG_R31
+       gc.Thearch.FREGMIN = mips.REG_F0
+       gc.Thearch.FREGMAX = mips.REG_F31
        gc.Thearch.MAXWIDTH = MAXWIDTH
        gc.Thearch.ReservedRegs = resvd
 
index 0322e85f5311dec4ec3b6fdf390d96b0e0553564..8c285a29525b5ed67596e96e0caaac7d0dd1c8f3 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
        "fmt"
 )
 
@@ -69,30 +69,35 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
        }
        if cnt < int64(4*gc.Widthptr) {
                for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
-                       p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, 8+frame+lo+i)
+                       p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGSP, 8+frame+lo+i)
                }
                // TODO(dfc): https://golang.org/issue/12108
                // If DUFFZERO is used inside a tail call (see genwrapper) it will
                // overwrite the link register.
        } else if false && cnt <= int64(128*gc.Widthptr) {
-               p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
-               p.Reg = ppc64.REGSP
+               p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+               p.Reg = mips.REGSP
                p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
                f := gc.Sysfunc("duffzero")
                gc.Naddr(&p.To, f)
                gc.Afunclit(&p.To, f)
-               p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
+               p.To.Offset = 8 * (128 - cnt/int64(gc.Widthptr))
        } else {
-               p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGTMP, 0)
-               p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT1, 0)
-               p.Reg = ppc64.REGSP
-               p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, ppc64.REGTMP, 0)
-               p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
-               p.Reg = ppc64.REGRT1
-               p = appendpp(p, ppc64.AMOVDU, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGRT1, int64(gc.Widthptr))
+               //      ADDV    $(8+frame+lo-8), SP, r1
+               //      ADDV    $cnt, r1, r2
+               // loop:
+               //      MOVV    R0, (Widthptr)r1
+               //      ADDV    $Widthptr, r1
+               //      BNE             r1, r2, loop
+               p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+               p.Reg = mips.REGSP
+               p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, mips.REGRT2, 0)
+               p.Reg = mips.REGRT1
+               p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGRT1, int64(gc.Widthptr))
                p1 := p
-               p = appendpp(p, ppc64.ACMP, obj.TYPE_REG, ppc64.REGRT1, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
-               p = appendpp(p, ppc64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
+               p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, mips.REGRT1, 0)
+               p = appendpp(p, mips.ABNE, obj.TYPE_REG, mips.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
+               p.Reg = mips.REGRT2
                gc.Patch(p, p1)
        }
 
@@ -117,8 +122,8 @@ func appendpp(p *obj.Prog, as int, ftype int, freg int, foffset int64, ttype int
 
 func ginsnop() {
        var reg gc.Node
-       gc.Nodreg(&reg, gc.Types[gc.TINT], ppc64.REG_R0)
-       gins(ppc64.AOR, &reg, &reg)
+       gc.Nodreg(&reg, gc.Types[gc.TINT], mips.REG_R0)
+       gins(mips.ANOR, &reg, &reg)
 }
 
 var panicdiv *gc.Node
@@ -131,25 +136,9 @@ var panicdiv *gc.Node
  * according to op.
  */
 func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
-       // Have to be careful about handling
-       // most negative int divided by -1 correctly.
-       // The hardware will generate undefined result.
-       // Also need to explicitly trap on division on zero,
-       // the hardware will silently generate undefined result.
-       // DIVW will leave unpredicable result in higher 32-bit,
-       // so always use DIVD/DIVDU.
        t := nl.Type
 
        t0 := t
-       check := 0
-       if gc.Issigned[t.Etype] {
-               check = 1
-               if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
-                       check = 0
-               } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
-                       check = 0
-               }
-       }
 
        if t.Width < 8 {
                if gc.Issigned[t.Etype] {
@@ -157,7 +146,6 @@ func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
                } else {
                        t = gc.Types[gc.TUINT64]
                }
-               check = 0
        }
 
        a := optoas(gc.ODIV, t)
@@ -186,65 +174,26 @@ func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
        }
 
        // Handle divide-by-zero panic.
-       p1 := gins(optoas(gc.OCMP, t), &tr, nil)
-
-       p1.To.Type = obj.TYPE_REG
-       p1.To.Reg = ppc64.REGZERO
-       p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
+       p1 := ginsbranch(mips.ABNE, nil, &tr, nil, 0)
        if panicdiv == nil {
                panicdiv = gc.Sysfunc("panicdivide")
        }
        gc.Ginscall(panicdiv, -1)
        gc.Patch(p1, gc.Pc)
 
-       var p2 *obj.Prog
-       if check != 0 {
-               var nm1 gc.Node
-               gc.Nodconst(&nm1, t, -1)
-               gins(optoas(gc.OCMP, t), &tr, &nm1)
-               p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
-               if op == gc.ODIV {
-                       // a / (-1) is -a.
-                       gins(optoas(gc.OMINUS, t), nil, &tl)
-
-                       gmove(&tl, res)
-               } else {
-                       // a % (-1) is 0.
-                       var nz gc.Node
-                       gc.Nodconst(&nz, t, 0)
-
-                       gmove(&nz, res)
-               }
-
-               p2 = gc.Gbranch(obj.AJMP, nil, 0)
-               gc.Patch(p1, gc.Pc)
-       }
-
-       p1 = gins(a, &tr, &tl)
+       gins3(a, &tr, &tl, nil)
+       gc.Regfree(&tr)
        if op == gc.ODIV {
-               gc.Regfree(&tr)
-               gmove(&tl, res)
-       } else {
-               // A%B = A-(A/B*B)
-               var tm gc.Node
-               gc.Regalloc(&tm, t, nil)
-
-               // patch div to use the 3 register form
-               // TODO(minux): add gins3?
-               p1.Reg = p1.To.Reg
-
-               p1.To.Reg = tm.Reg
-               gins(optoas(gc.OMUL, t), &tr, &tm)
-               gc.Regfree(&tr)
-               gins(optoas(gc.OSUB, t), &tm, &tl)
-               gc.Regfree(&tm)
-               gmove(&tl, res)
+               var lo gc.Node
+               gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+               gins(mips.AMOVV, &lo, &tl)
+       } else { // remainder in REG_HI
+               var hi gc.Node
+               gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+               gins(mips.AMOVV, &hi, &tl)
        }
-
+       gmove(&tl, res)
        gc.Regfree(&tl)
-       if check != 0 {
-               gc.Patch(p2, gc.Pc)
-       }
 }
 
 /*
@@ -254,9 +203,7 @@ func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
        // largest ullman on left.
        if nl.Ullman < nr.Ullman {
-               tmp := (*gc.Node)(nl)
-               nl = nr
-               nr = tmp
+               nl, nr = nr, nl
        }
 
        t := (*gc.Type)(nl.Type)
@@ -269,26 +216,35 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
        case gc.TINT8,
                gc.TINT16,
                gc.TINT32:
-               gins(optoas(gc.OMUL, t), &n2, &n1)
-               p := (*obj.Prog)(gins(ppc64.ASRAD, nil, &n1))
+               gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+               var lo gc.Node
+               gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+               gins(mips.AMOVV, &lo, &n1)
+               p := (*obj.Prog)(gins(mips.ASRAV, nil, &n1))
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(w)
 
        case gc.TUINT8,
                gc.TUINT16,
                gc.TUINT32:
-               gins(optoas(gc.OMUL, t), &n2, &n1)
-               p := (*obj.Prog)(gins(ppc64.ASRD, nil, &n1))
+               gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+               var lo gc.Node
+               gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+               gins(mips.AMOVV, &lo, &n1)
+               p := (*obj.Prog)(gins(mips.ASRLV, nil, &n1))
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = int64(w)
 
        case gc.TINT64,
                gc.TUINT64:
                if gc.Issigned[t.Etype] {
-                       gins(ppc64.AMULHD, &n2, &n1)
+                       gins3(mips.AMULV, &n2, &n1, nil)
                } else {
-                       gins(ppc64.AMULHDU, &n2, &n1)
+                       gins3(mips.AMULVU, &n2, &n1, nil)
                }
+               var hi gc.Node
+               gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+               gins(mips.AMOVV, &hi, &n1)
 
        default:
                gc.Fatalf("cgen_hmul %v", t)
@@ -372,9 +328,11 @@ func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node)
 
        // test and fix up large shifts
        if !bounded {
+               var rtmp gc.Node
+               gc.Nodreg(&rtmp, tcount, mips.REGTMP)
                gc.Nodconst(&n3, tcount, nl.Type.Width*8)
-               gins(optoas(gc.OCMP, tcount), &n1, &n3)
-               p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, tcount), nil, +1))
+               gins3(mips.ASGTU, &n3, &n1, &rtmp)
+               p1 := ginsbranch(mips.ABNE, nil, &rtmp, nil, 0)
                if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
                        gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
                        gins(a, &n3, &n2)
@@ -410,61 +368,64 @@ func clearfat(nl *gc.Node) {
        c := uint64(w % 8) // bytes
        q := uint64(w / 8) // dwords
 
-       if gc.Reginuse(ppc64.REGRT1) {
-               gc.Fatalf("%v in use during clearfat", obj.Rconv(ppc64.REGRT1))
+       if gc.Reginuse(mips.REGRT1) {
+               gc.Fatalf("%v in use during clearfat", obj.Rconv(mips.REGRT1))
        }
 
        var r0 gc.Node
-       gc.Nodreg(&r0, gc.Types[gc.TUINT64], ppc64.REGZERO)
+       gc.Nodreg(&r0, gc.Types[gc.TUINT64], mips.REGZERO)
        var dst gc.Node
-       gc.Nodreg(&dst, gc.Types[gc.Tptr], ppc64.REGRT1)
+       gc.Nodreg(&dst, gc.Types[gc.Tptr], mips.REGRT1)
        gc.Regrealloc(&dst)
        gc.Agen(nl, &dst)
 
        var boff uint64
        if q > 128 {
-               p := gins(ppc64.ASUB, nil, &dst)
+               p := gins(mips.ASUBV, nil, &dst)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = 8
 
                var end gc.Node
                gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
-               p = gins(ppc64.AMOVD, &dst, &end)
+               p = gins(mips.AMOVV, &dst, &end)
                p.From.Type = obj.TYPE_ADDR
                p.From.Offset = int64(q * 8)
 
-               p = gins(ppc64.AMOVDU, &r0, &dst)
+               p = gins(mips.AMOVV, &r0, &dst)
                p.To.Type = obj.TYPE_MEM
                p.To.Offset = 8
                pl := (*obj.Prog)(p)
 
-               p = gins(ppc64.ACMP, &dst, &end)
-               gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), pl)
+               p = gins(mips.AADDV, nil, &dst)
+               p.From.Type = obj.TYPE_CONST
+               p.From.Offset = 8
+
+               gc.Patch(ginsbranch(mips.ABNE, nil, &dst, &end, 0), pl)
 
                gc.Regfree(&end)
 
-               // The loop leaves R3 on the last zeroed dword
+               // The loop leaves R1 on the last zeroed dword
                boff = 8
                // TODO(dfc): https://golang.org/issue/12108
                // If DUFFZERO is used inside a tail call (see genwrapper) it will
                // overwrite the link register.
        } else if false && q >= 4 {
-               p := gins(ppc64.ASUB, nil, &dst)
+               p := gins(mips.ASUBV, nil, &dst)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = 8
                f := (*gc.Node)(gc.Sysfunc("duffzero"))
                p = gins(obj.ADUFFZERO, nil, f)
                gc.Afunclit(&p.To, f)
 
-               // 4 and 128 = magic constants: see ../../runtime/asm_ppc64x.s
-               p.To.Offset = int64(4 * (128 - q))
+               // 8 and 128 = magic constants: see ../../runtime/asm_mips64x.s
+               p.To.Offset = int64(8 * (128 - q))
 
-               // duffzero leaves R3 on the last zeroed dword
+               // duffzero leaves R1 on the last zeroed dword
                boff = 8
        } else {
                var p *obj.Prog
                for t := uint64(0); t < q; t++ {
-                       p = gins(ppc64.AMOVD, &r0, &dst)
+                       p = gins(mips.AMOVV, &r0, &dst)
                        p.To.Type = obj.TYPE_MEM
                        p.To.Offset = int64(8 * t)
                }
@@ -474,7 +435,7 @@ func clearfat(nl *gc.Node) {
 
        var p *obj.Prog
        for t := uint64(0); t < c; t++ {
-               p = gins(ppc64.AMOVB, &r0, &dst)
+               p = gins(mips.AMOVB, &r0, &dst)
                p.To.Type = obj.TYPE_MEM
                p.To.Offset = int64(t + boff)
        }
@@ -486,7 +447,6 @@ func clearfat(nl *gc.Node) {
 // Expand CHECKNIL pseudo-op into actual nil pointer check.
 func expandchecks(firstp *obj.Prog) {
        var p1 *obj.Prog
-       var p2 *obj.Prog
 
        for p := (*obj.Prog)(firstp); p != nil; p = p.Link {
                if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 {
@@ -502,63 +462,33 @@ func expandchecks(firstp *obj.Prog) {
                        gc.Fatalf("invalid nil check %v\n", p)
                }
 
-               /*
-                       // check is
-                       //      TD $4, R0, arg (R0 is always zero)
-                       // eqv. to:
-                       //      tdeq r0, arg
-                       // NOTE: this needs special runtime support to make SIGTRAP recoverable.
-                       reg = p->from.reg;
-                       p->as = ATD;
-                       p->from = p->to = p->from3 = zprog.from;
-                       p->from.type = TYPE_CONST;
-                       p->from.offset = 4;
-                       p->from.reg = 0;
-                       p->reg = REGZERO;
-                       p->to.type = TYPE_REG;
-                       p->to.reg = reg;
-               */
                // check is
-               //      CMP arg, R0
-               //      BNE 2(PC) [likely]
-               //      MOVD R0, 0(R0)
+               //      BNE arg, 2(PC)
+               //      MOVV R0, 0(R0)
                p1 = gc.Ctxt.NewProg()
-
-               p2 = gc.Ctxt.NewProg()
                gc.Clearp(p1)
-               gc.Clearp(p2)
-               p1.Link = p2
-               p2.Link = p.Link
+               p1.Link = p.Link
                p.Link = p1
                p1.Lineno = p.Lineno
-               p2.Lineno = p.Lineno
                p1.Pc = 9999
-               p2.Pc = 9999
-               p.As = ppc64.ACMP
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = ppc64.REGZERO
-               p1.As = ppc64.ABNE
 
-               //p1->from.type = TYPE_CONST;
-               //p1->from.offset = 1; // likely
-               p1.To.Type = obj.TYPE_BRANCH
-
-               p1.To.Val = p2.Link
+               p.As = mips.ABNE
+               p.To.Type = obj.TYPE_BRANCH
+               p.To.Val = p1.Link
 
                // crash by write to memory address 0.
-               p2.As = ppc64.AMOVD
-
-               p2.From.Type = obj.TYPE_REG
-               p2.From.Reg = ppc64.REGZERO
-               p2.To.Type = obj.TYPE_MEM
-               p2.To.Reg = ppc64.REGZERO
-               p2.To.Offset = 0
+               p1.As = mips.AMOVV
+               p1.From.Type = obj.TYPE_REG
+               p1.From.Reg = mips.REGZERO
+               p1.To.Type = obj.TYPE_MEM
+               p1.To.Reg = mips.REGZERO
+               p1.To.Offset = 0
        }
 }
 
 // res = runtime.getg()
 func getg(res *gc.Node) {
        var n1 gc.Node
-       gc.Nodreg(&n1, res.Type, ppc64.REGG)
+       gc.Nodreg(&n1, res.Type, mips.REGG)
        gmove(&n1, res)
 }
index f0cf2e16c914f8d2e6ed3e69f35d5b26997d5154..d2065d9d2e6af0d51cfe528e1ba6ae08232b4aa7 100644 (file)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/big"
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
        "fmt"
 )
 
 var resvd = []int{
-       ppc64.REGZERO,
-       ppc64.REGSP, // reserved for SP
-       // We need to preserve the C ABI TLS pointer because sigtramp
-       // may happen during C code and needs to access the g.  C
-       // clobbers REGG, so if Go were to clobber REGTLS, sigtramp
-       // won't know which convention to use.  By preserving REGTLS,
-       // we can just retrieve g from TLS when we aren't sure.
-       ppc64.REGTLS,
-
-       // TODO(austin): Consolidate REGTLS and REGG?
-       ppc64.REGG,
-       ppc64.REGTMP, // REGTMP
-       ppc64.FREGCVI,
-       ppc64.FREGZERO,
-       ppc64.FREGHALF,
-       ppc64.FREGONE,
-       ppc64.FREGTWO,
+       mips.REGZERO,
+       mips.REGSP,   // reserved for SP
+       mips.REGLINK, // reserved for link
+       mips.REGG,
+       mips.REGTMP,
+       mips.REG_R26, // kernel
+       mips.REG_R27, // kernel
+       mips.FREGZERO,
+       mips.FREGHALF,
+       mips.FREGONE,
+       mips.FREGTWO,
 }
 
 /*
@@ -67,13 +61,13 @@ func ginscon(as int, c int64, n2 *gc.Node) {
 
        gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
 
-       if as != ppc64.AMOVD && (c < -ppc64.BIG || c > ppc64.BIG) || n2.Op != gc.OREGISTER || as == ppc64.AMULLD {
+       if as != mips.AMOVV && (c < -mips.BIG || c > mips.BIG) || n2.Op != gc.OREGISTER || as == mips.AMUL || as == mips.AMULU || as == mips.AMULV || as == mips.AMULVU {
                // cannot have more than 16-bit of immediate in ADD, etc.
                // instead, MOV into register first.
                var ntmp gc.Node
                gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
 
-               rawgins(ppc64.AMOVD, &n1, &ntmp)
+               rawgins(mips.AMOVV, &n1, &ntmp)
                rawgins(as, &ntmp, n2)
                gc.Regfree(&ntmp)
                return
@@ -82,46 +76,30 @@ func ginscon(as int, c int64, n2 *gc.Node) {
        rawgins(as, &n1, n2)
 }
 
-/*
- * generate
- *     as n, $c (CMP/CMPU)
- */
-func ginscon2(as int, n2 *gc.Node, c int64) {
-       var n1 gc.Node
-
-       gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
-
-       switch as {
-       default:
-               gc.Fatalf("ginscon2")
-
-       case ppc64.ACMP:
-               if -ppc64.BIG <= c && c <= ppc64.BIG {
-                       rawgins(as, n2, &n1)
-                       return
-               }
-
-       case ppc64.ACMPU:
-               if 0 <= c && c <= 2*ppc64.BIG {
-                       rawgins(as, n2, &n1)
-                       return
-               }
+// generate branch
+// n1, n2 are registers
+func ginsbranch(as int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+       p := gc.Gbranch(as, t, likely)
+       gc.Naddr(&p.From, n1)
+       if n2 != nil {
+               p.Reg = n2.Reg
        }
-
-       // MOV n1 into register first
-       var ntmp gc.Node
-       gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
-
-       rawgins(ppc64.AMOVD, &n1, &ntmp)
-       rawgins(as, n2, &ntmp)
-       gc.Regfree(&ntmp)
+       return p
 }
 
 func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
-       if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
-               // Reverse comparison to place constant last.
-               op = gc.Brrev(op)
+       if !gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OGE) {
+               // swap nodes to fit SGT instruction
+               n1, n2 = n2, n1
+       }
+       if gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OLE) {
+               // swap nodes to fit CMPGT, CMPGE instructions and reverse relation
                n1, n2 = n2, n1
+               if op == gc.OLT {
+                       op = gc.OGT
+               } else {
+                       op = gc.OGE
+               }
        }
 
        var r1, r2, g1, g2 gc.Node
@@ -129,20 +107,85 @@ func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
        gc.Regalloc(&g1, n1.Type, &r1)
        gc.Cgen(n1, &g1)
        gmove(&g1, &r1)
-       if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
-               ginscon2(optoas(gc.OCMP, t), &r1, n2.Int())
-       } else {
-               gc.Regalloc(&r2, t, n2)
-               gc.Regalloc(&g2, n1.Type, &r2)
-               gc.Cgen(n2, &g2)
-               gmove(&g2, &r2)
-               rawgins(optoas(gc.OCMP, t), &r1, &r2)
-               gc.Regfree(&g2)
-               gc.Regfree(&r2)
+
+       gc.Regalloc(&r2, t, n2)
+       gc.Regalloc(&g2, n1.Type, &r2)
+       gc.Cgen(n2, &g2)
+       gmove(&g2, &r2)
+
+       var p *obj.Prog
+       var ntmp gc.Node
+       gc.Nodreg(&ntmp, gc.Types[gc.TINT], mips.REGTMP)
+
+       switch gc.Simtype[t.Etype] {
+       case gc.TINT8,
+               gc.TINT16,
+               gc.TINT32,
+               gc.TINT64:
+               if op == gc.OEQ || op == gc.ONE {
+                       p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+               } else {
+                       gins3(mips.ASGT, &r1, &r2, &ntmp)
+
+                       p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+               }
+
+       case gc.TBOOL,
+               gc.TUINT8,
+               gc.TUINT16,
+               gc.TUINT32,
+               gc.TUINT64,
+               gc.TPTR32,
+               gc.TPTR64:
+               if op == gc.OEQ || op == gc.ONE {
+                       p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+               } else {
+                       gins3(mips.ASGTU, &r1, &r2, &ntmp)
+
+                       p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+               }
+
+       case gc.TFLOAT32:
+               switch op {
+               default:
+                       gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+               case gc.OEQ,
+                       gc.ONE:
+                       gins3(mips.ACMPEQF, &r1, &r2, nil)
+
+               case gc.OGE:
+                       gins3(mips.ACMPGEF, &r1, &r2, nil)
+
+               case gc.OGT:
+                       gins3(mips.ACMPGTF, &r1, &r2, nil)
+               }
+               p = gc.Gbranch(optoas(op, t), nil, likely)
+
+       case gc.TFLOAT64:
+               switch op {
+               default:
+                       gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+               case gc.OEQ,
+                       gc.ONE:
+                       gins3(mips.ACMPEQD, &r1, &r2, nil)
+
+               case gc.OGE:
+                       gins3(mips.ACMPGED, &r1, &r2, nil)
+
+               case gc.OGT:
+                       gins3(mips.ACMPGTD, &r1, &r2, nil)
+               }
+               p = gc.Gbranch(optoas(op, t), nil, likely)
        }
+
+       gc.Regfree(&g2)
+       gc.Regfree(&r2)
        gc.Regfree(&g1)
        gc.Regfree(&r1)
-       return gc.Gbranch(optoas(op, t), nil, likely)
+
+       return p
 }
 
 // set up nodes representing 2^63
@@ -209,7 +252,7 @@ func gmove(f *gc.Node, t *gc.Node) {
                        f.Convconst(&con, gc.Types[gc.TINT64])
                        var r1 gc.Node
                        gc.Regalloc(&r1, con.Type, t)
-                       gins(ppc64.AMOVD, &con, &r1)
+                       gins(mips.AMOVV, &con, &r1)
                        gmove(&r1, t)
                        gc.Regfree(&r1)
                        return
@@ -221,7 +264,7 @@ func gmove(f *gc.Node, t *gc.Node) {
                        f.Convconst(&con, gc.Types[gc.TUINT64])
                        var r1 gc.Node
                        gc.Regalloc(&r1, con.Type, t)
-                       gins(ppc64.AMOVD, &con, &r1)
+                       gins(mips.AMOVV, &con, &r1)
                        gmove(&r1, t)
                        gc.Regfree(&r1)
                        return
@@ -236,21 +279,13 @@ func gmove(f *gc.Node, t *gc.Node) {
                }
        }
 
-       // float constants come from memory.
-       //if(isfloat[tt])
-       //      goto hard;
-
-       // 64-bit immediates are also from memory.
-       //if(isint[tt])
-       //      goto hard;
-       //// 64-bit immediates are really 32-bit sign-extended
-       //// unless moving into a register.
-       //if(isint[tt]) {
-       //      if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
-       //              goto hard;
-       //      if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
-       //              goto hard;
-       //}
+       // value -> value copy, first operand in memory.
+       // any floating point operand requires register
+       // src, so goto hard to copy to register first.
+       if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) {
+               cvt = gc.Types[ft]
+               goto hard
+       }
 
        // value -> value copy, only one memory operand.
        // figure out the instruction to use.
@@ -268,62 +303,57 @@ func gmove(f *gc.Node, t *gc.Node) {
                 */
        case gc.TINT8<<16 | gc.TINT8, // same size
                gc.TUINT8<<16 | gc.TINT8,
-               gc.TINT16<<16 | gc.TINT8,
-               // truncate
+               gc.TINT16<<16 | gc.TINT8, // truncate
                gc.TUINT16<<16 | gc.TINT8,
                gc.TINT32<<16 | gc.TINT8,
                gc.TUINT32<<16 | gc.TINT8,
                gc.TINT64<<16 | gc.TINT8,
                gc.TUINT64<<16 | gc.TINT8:
-               a = ppc64.AMOVB
+               a = mips.AMOVB
 
        case gc.TINT8<<16 | gc.TUINT8, // same size
                gc.TUINT8<<16 | gc.TUINT8,
-               gc.TINT16<<16 | gc.TUINT8,
-               // truncate
+               gc.TINT16<<16 | gc.TUINT8, // truncate
                gc.TUINT16<<16 | gc.TUINT8,
                gc.TINT32<<16 | gc.TUINT8,
                gc.TUINT32<<16 | gc.TUINT8,
                gc.TINT64<<16 | gc.TUINT8,
                gc.TUINT64<<16 | gc.TUINT8:
-               a = ppc64.AMOVBZ
+               a = mips.AMOVBU
 
        case gc.TINT16<<16 | gc.TINT16, // same size
                gc.TUINT16<<16 | gc.TINT16,
-               gc.TINT32<<16 | gc.TINT16,
-               // truncate
+               gc.TINT32<<16 | gc.TINT16, // truncate
                gc.TUINT32<<16 | gc.TINT16,
                gc.TINT64<<16 | gc.TINT16,
                gc.TUINT64<<16 | gc.TINT16:
-               a = ppc64.AMOVH
+               a = mips.AMOVH
 
        case gc.TINT16<<16 | gc.TUINT16, // same size
                gc.TUINT16<<16 | gc.TUINT16,
-               gc.TINT32<<16 | gc.TUINT16,
-               // truncate
+               gc.TINT32<<16 | gc.TUINT16, // truncate
                gc.TUINT32<<16 | gc.TUINT16,
                gc.TINT64<<16 | gc.TUINT16,
                gc.TUINT64<<16 | gc.TUINT16:
-               a = ppc64.AMOVHZ
+               a = mips.AMOVHU
 
        case gc.TINT32<<16 | gc.TINT32, // same size
                gc.TUINT32<<16 | gc.TINT32,
-               gc.TINT64<<16 | gc.TINT32,
-               // truncate
+               gc.TINT64<<16 | gc.TINT32, // truncate
                gc.TUINT64<<16 | gc.TINT32:
-               a = ppc64.AMOVW
+               a = mips.AMOVW
 
        case gc.TINT32<<16 | gc.TUINT32, // same size
                gc.TUINT32<<16 | gc.TUINT32,
-               gc.TINT64<<16 | gc.TUINT32,
+               gc.TINT64<<16 | gc.TUINT32, // truncate
                gc.TUINT64<<16 | gc.TUINT32:
-               a = ppc64.AMOVWZ
+               a = mips.AMOVWU
 
        case gc.TINT64<<16 | gc.TINT64, // same size
                gc.TINT64<<16 | gc.TUINT64,
                gc.TUINT64<<16 | gc.TINT64,
                gc.TUINT64<<16 | gc.TUINT64:
-               a = ppc64.AMOVD
+               a = mips.AMOVV
 
                /*
                 * integer up-conversions
@@ -334,7 +364,7 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TINT8<<16 | gc.TUINT32,
                gc.TINT8<<16 | gc.TINT64,
                gc.TINT8<<16 | gc.TUINT64:
-               a = ppc64.AMOVB
+               a = mips.AMOVB
 
                goto rdst
 
@@ -344,7 +374,7 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TUINT8<<16 | gc.TUINT32,
                gc.TUINT8<<16 | gc.TINT64,
                gc.TUINT8<<16 | gc.TUINT64:
-               a = ppc64.AMOVBZ
+               a = mips.AMOVBU
 
                goto rdst
 
@@ -352,7 +382,7 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TINT16<<16 | gc.TUINT32,
                gc.TINT16<<16 | gc.TINT64,
                gc.TINT16<<16 | gc.TUINT64:
-               a = ppc64.AMOVH
+               a = mips.AMOVH
 
                goto rdst
 
@@ -360,19 +390,19 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TUINT16<<16 | gc.TUINT32,
                gc.TUINT16<<16 | gc.TINT64,
                gc.TUINT16<<16 | gc.TUINT64:
-               a = ppc64.AMOVHZ
+               a = mips.AMOVHU
 
                goto rdst
 
        case gc.TINT32<<16 | gc.TINT64, // sign extend int32
                gc.TINT32<<16 | gc.TUINT64:
-               a = ppc64.AMOVW
+               a = mips.AMOVW
 
                goto rdst
 
        case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
                gc.TUINT32<<16 | gc.TUINT64:
-               a = ppc64.AMOVWZ
+               a = mips.AMOVWU
 
                goto rdst
 
@@ -402,49 +432,39 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TFLOAT64<<16 | gc.TUINT64:
                bignodes()
 
-               var r1 gc.Node
-               gc.Regalloc(&r1, gc.Types[ft], f)
+               gc.Regalloc(&r1, gc.Types[gc.TFLOAT64], nil)
                gmove(f, &r1)
                if tt == gc.TUINT64 {
                        gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
                        gmove(&bigf, &r2)
-                       gins(ppc64.AFCMPU, &r1, &r2)
-                       p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1))
-                       gins(ppc64.AFSUB, &r2, &r1)
+                       gins3(mips.ACMPGED, &r1, &r2, nil)
+                       p1 := gc.Gbranch(mips.ABFPF, nil, 0)
+                       gins(mips.ASUBD, &r2, &r1)
                        gc.Patch(p1, gc.Pc)
                        gc.Regfree(&r2)
                }
 
-               gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
-               var r3 gc.Node
-               gc.Regalloc(&r3, gc.Types[gc.TINT64], t)
-               gins(ppc64.AFCTIDZ, &r1, &r2)
-               p1 := (*obj.Prog)(gins(ppc64.AFMOVD, &r2, nil))
-               p1.To.Type = obj.TYPE_MEM
-               p1.To.Reg = ppc64.REGSP
-               p1.To.Offset = -8
-               p1 = gins(ppc64.AMOVD, nil, &r3)
-               p1.From.Type = obj.TYPE_MEM
-               p1.From.Reg = ppc64.REGSP
-               p1.From.Offset = -8
-               gc.Regfree(&r2)
+               gc.Regalloc(&r2, gc.Types[gc.TINT64], t)
+               gins(mips.ATRUNCDV, &r1, &r1)
+               gins(mips.AMOVV, &r1, &r2)
                gc.Regfree(&r1)
+
                if tt == gc.TUINT64 {
-                       p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1)) // use CR0 here again
-                       gc.Nodreg(&r1, gc.Types[gc.TINT64], ppc64.REGTMP)
-                       gins(ppc64.AMOVD, &bigi, &r1)
-                       gins(ppc64.AADD, &r1, &r3)
+                       p1 := gc.Gbranch(mips.ABFPF, nil, 0) // use FCR0 here again
+                       gc.Nodreg(&r1, gc.Types[gc.TINT64], mips.REGTMP)
+                       gmove(&bigi, &r1)
+                       gins(mips.AADDVU, &r1, &r2)
                        gc.Patch(p1, gc.Pc)
                }
 
-               gmove(&r3, t)
-               gc.Regfree(&r3)
+               gmove(&r2, t)
+               gc.Regfree(&r2)
                return
 
                //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
        //return;
        // algorithm is:
-       //      if small enough, use native int64 -> uint64 conversion.
+       //      if small enough, use native int64 -> float64 conversion.
        //      otherwise, halve (rounding to odd?), convert, and double.
        /*
         * integer to float
@@ -467,35 +487,29 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TUINT64<<16 | gc.TFLOAT64:
                bignodes()
 
-               var r1 gc.Node
+               var rtmp gc.Node
                gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
                gmove(f, &r1)
                if ft == gc.TUINT64 {
-                       gc.Nodreg(&r2, gc.Types[gc.TUINT64], ppc64.REGTMP)
-                       gmove(&bigi, &r2)
-                       gins(ppc64.ACMPU, &r1, &r2)
-                       p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1))
-                       p2 := (*obj.Prog)(gins(ppc64.ASRD, nil, &r1))
+                       gc.Nodreg(&rtmp, gc.Types[gc.TUINT64], mips.REGTMP)
+                       gmove(&bigi, &rtmp)
+                       gins(mips.AAND, &r1, &rtmp)
+                       p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+                       p2 := gins(mips.ASRLV, nil, &r1)
                        p2.From.Type = obj.TYPE_CONST
                        p2.From.Offset = 1
                        gc.Patch(p1, gc.Pc)
                }
 
                gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
-               p1 := (*obj.Prog)(gins(ppc64.AMOVD, &r1, nil))
-               p1.To.Type = obj.TYPE_MEM
-               p1.To.Reg = ppc64.REGSP
-               p1.To.Offset = -8
-               p1 = gins(ppc64.AFMOVD, nil, &r2)
-               p1.From.Type = obj.TYPE_MEM
-               p1.From.Reg = ppc64.REGSP
-               p1.From.Offset = -8
-               gins(ppc64.AFCFID, &r2, &r2)
+               gins(mips.AMOVV, &r1, &r2)
+               gins(mips.AMOVVD, &r2, &r2)
                gc.Regfree(&r1)
+
                if ft == gc.TUINT64 {
-                       p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1)) // use CR0 here again
-                       gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], ppc64.FREGTWO)
-                       gins(ppc64.AFMUL, &r1, &r2)
+                       p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+                       gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], mips.FREGTWO)
+                       gins(mips.AMULD, &r1, &r2)
                        gc.Patch(p1, gc.Pc)
                }
 
@@ -507,17 +521,17 @@ func gmove(f *gc.Node, t *gc.Node) {
                 * float to float
                 */
        case gc.TFLOAT32<<16 | gc.TFLOAT32:
-               a = ppc64.AFMOVS
+               a = mips.AMOVF
 
        case gc.TFLOAT64<<16 | gc.TFLOAT64:
-               a = ppc64.AFMOVD
+               a = mips.AMOVD
 
        case gc.TFLOAT32<<16 | gc.TFLOAT64:
-               a = ppc64.AFMOVS
+               a = mips.AMOVFD
                goto rdst
 
        case gc.TFLOAT64<<16 | gc.TFLOAT32:
-               a = ppc64.AFRSP
+               a = mips.AMOVDF
                goto rdst
        }
 
@@ -555,15 +569,22 @@ func gins(as int, f, t *gc.Node) *obj.Prog {
                        return nil // caller must not use
                }
        }
-       if as == ppc64.ACMP || as == ppc64.ACMPU {
-               if x, ok := t.IntLiteral(); ok {
-                       ginscon2(as, f, x)
-                       return nil // caller must not use
-               }
-       }
        return rawgins(as, f, t)
 }
 
+/*
+ * generate one instruction:
+ *     as f, r, t
+ * r must be register, if not nil
+ */
+func gins3(as int, f, r, t *gc.Node) *obj.Prog {
+       p := rawgins(as, f, t)
+       if r != nil {
+               p.Reg = r.Reg
+       }
+       return p
+}
+
 /*
  * generate one instruction:
  *     as f, t
@@ -578,37 +599,52 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 
        switch as {
        case obj.ACALL:
-               if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR {
-                       // Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR.
-                       pp := gc.Prog(as)
-                       pp.From = p.From
-                       pp.To.Type = obj.TYPE_REG
-                       pp.To.Reg = ppc64.REG_CTR
-
-                       p.As = ppc64.AMOVD
-                       p.From = p.To
-                       p.To.Type = obj.TYPE_REG
-                       p.To.Reg = ppc64.REG_CTR
+               if p.To.Type == obj.TYPE_REG {
+                       // Allow front end to emit CALL REG, and rewrite into CALL (REG).
+                       p.From = obj.Addr{}
+                       p.To.Type = obj.TYPE_MEM
+                       p.To.Offset = 0
 
                        if gc.Debug['g'] != 0 {
                                fmt.Printf("%v\n", p)
-                               fmt.Printf("%v\n", pp)
                        }
 
-                       return pp
+                       return p
                }
 
        // Bad things the front end has done to us. Crash to find call stack.
-       case ppc64.AAND, ppc64.AMULLD:
+       case mips.AAND:
                if p.From.Type == obj.TYPE_CONST {
                        gc.Debug['h'] = 1
                        gc.Fatalf("bad inst: %v", p)
                }
-       case ppc64.ACMP, ppc64.ACMPU:
+       case mips.ASGT, mips.ASGTU:
                if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
                        gc.Debug['h'] = 1
                        gc.Fatalf("bad inst: %v", p)
                }
+
+       // Special cases
+       case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU:
+               if p.From.Type == obj.TYPE_CONST {
+                       gc.Debug['h'] = 1
+                       gc.Fatalf("bad inst: %v", p)
+               }
+
+               pp := gc.Prog(mips.AMOVV)
+               pp.From.Type = obj.TYPE_REG
+               pp.From.Reg = mips.REG_LO
+               pp.To = p.To
+
+               p.Reg = p.To.Reg
+               p.To = obj.Addr{}
+
+       case mips.ASUBVU:
+               // unary
+               if f == nil {
+                       p.From = p.To
+                       p.Reg = mips.REGZERO
+               }
        }
 
        if gc.Debug['g'] != 0 {
@@ -617,26 +653,19 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 
        w := int32(0)
        switch as {
-       case ppc64.AMOVB,
-               ppc64.AMOVBU,
-               ppc64.AMOVBZ,
-               ppc64.AMOVBZU:
+       case mips.AMOVB,
+               mips.AMOVBU:
                w = 1
 
-       case ppc64.AMOVH,
-               ppc64.AMOVHU,
-               ppc64.AMOVHZ,
-               ppc64.AMOVHZU:
+       case mips.AMOVH,
+               mips.AMOVHU:
                w = 2
 
-       case ppc64.AMOVW,
-               ppc64.AMOVWU,
-               ppc64.AMOVWZ,
-               ppc64.AMOVWZU:
+       case mips.AMOVW,
+               mips.AMOVWU:
                w = 4
 
-       case ppc64.AMOVD,
-               ppc64.AMOVDU:
+       case mips.AMOVV:
                if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
                        break
                }
@@ -698,10 +727,12 @@ func optoas(op gc.Op, t *gc.Type) int {
                OEQ_ | gc.TINT64,
                OEQ_ | gc.TUINT64,
                OEQ_ | gc.TPTR32,
-               OEQ_ | gc.TPTR64,
-               OEQ_ | gc.TFLOAT32,
-               OEQ_ | gc.TFLOAT64:
-               a = ppc64.ABEQ
+               OEQ_ | gc.TPTR64:
+               a = mips.ABEQ
+
+       case OEQ_ | gc.TFLOAT32, // ACMPEQF
+               OEQ_ | gc.TFLOAT64: // ACMPEQD
+               a = mips.ABFPT
 
        case ONE_ | gc.TBOOL,
                ONE_ | gc.TINT8,
@@ -713,111 +744,99 @@ func optoas(op gc.Op, t *gc.Type) int {
                ONE_ | gc.TINT64,
                ONE_ | gc.TUINT64,
                ONE_ | gc.TPTR32,
-               ONE_ | gc.TPTR64,
-               ONE_ | gc.TFLOAT32,
-               ONE_ | gc.TFLOAT64:
-               a = ppc64.ABNE
+               ONE_ | gc.TPTR64:
+               a = mips.ABNE
 
-       case OLT_ | gc.TINT8, // ACMP
+       case ONE_ | gc.TFLOAT32, // ACMPEQF
+               ONE_ | gc.TFLOAT64: // ACMPEQD
+               a = mips.ABFPF
+
+       case OLT_ | gc.TINT8, // ASGT
                OLT_ | gc.TINT16,
                OLT_ | gc.TINT32,
                OLT_ | gc.TINT64,
-               OLT_ | gc.TUINT8,
-               // ACMPU
+               OLT_ | gc.TUINT8, // ASGTU
                OLT_ | gc.TUINT16,
                OLT_ | gc.TUINT32,
-               OLT_ | gc.TUINT64,
-               OLT_ | gc.TFLOAT32,
-               // AFCMPU
-               OLT_ | gc.TFLOAT64:
-               a = ppc64.ABLT
+               OLT_ | gc.TUINT64:
+               a = mips.ABNE
+
+       case OLT_ | gc.TFLOAT32, // ACMPGEF
+               OLT_ | gc.TFLOAT64: // ACMPGED
+               a = mips.ABFPT
 
-       case OLE_ | gc.TINT8, // ACMP
+       case OLE_ | gc.TINT8, // ASGT
                OLE_ | gc.TINT16,
                OLE_ | gc.TINT32,
                OLE_ | gc.TINT64,
-               OLE_ | gc.TUINT8,
-               // ACMPU
+               OLE_ | gc.TUINT8, // ASGTU
                OLE_ | gc.TUINT16,
                OLE_ | gc.TUINT32,
                OLE_ | gc.TUINT64:
-               // No OLE for floats, because it mishandles NaN.
-               // Front end must reverse comparison or use OLT and OEQ together.
-               a = ppc64.ABLE
+               a = mips.ABEQ
 
-       case OGT_ | gc.TINT8,
+       case OLE_ | gc.TFLOAT32, // ACMPGTF
+               OLE_ | gc.TFLOAT64: // ACMPGTD
+               a = mips.ABFPT
+
+       case OGT_ | gc.TINT8, // ASGT
                OGT_ | gc.TINT16,
                OGT_ | gc.TINT32,
                OGT_ | gc.TINT64,
-               OGT_ | gc.TUINT8,
+               OGT_ | gc.TUINT8, // ASGTU
                OGT_ | gc.TUINT16,
                OGT_ | gc.TUINT32,
-               OGT_ | gc.TUINT64,
-               OGT_ | gc.TFLOAT32,
-               OGT_ | gc.TFLOAT64:
-               a = ppc64.ABGT
+               OGT_ | gc.TUINT64:
+               a = mips.ABNE
+
+       case OGT_ | gc.TFLOAT32, // ACMPGTF
+               OGT_ | gc.TFLOAT64: // ACMPGTD
+               a = mips.ABFPT
 
-       case OGE_ | gc.TINT8,
+       case OGE_ | gc.TINT8, // ASGT
                OGE_ | gc.TINT16,
                OGE_ | gc.TINT32,
                OGE_ | gc.TINT64,
-               OGE_ | gc.TUINT8,
+               OGE_ | gc.TUINT8, // ASGTU
                OGE_ | gc.TUINT16,
                OGE_ | gc.TUINT32,
                OGE_ | gc.TUINT64:
-               // No OGE for floats, because it mishandles NaN.
-               // Front end must reverse comparison or use OLT and OEQ together.
-               a = ppc64.ABGE
-
-       case OCMP_ | gc.TBOOL,
-               OCMP_ | gc.TINT8,
-               OCMP_ | gc.TINT16,
-               OCMP_ | gc.TINT32,
-               OCMP_ | gc.TPTR32,
-               OCMP_ | gc.TINT64:
-               a = ppc64.ACMP
-
-       case OCMP_ | gc.TUINT8,
-               OCMP_ | gc.TUINT16,
-               OCMP_ | gc.TUINT32,
-               OCMP_ | gc.TUINT64,
-               OCMP_ | gc.TPTR64:
-               a = ppc64.ACMPU
-
-       case OCMP_ | gc.TFLOAT32,
-               OCMP_ | gc.TFLOAT64:
-               a = ppc64.AFCMPU
+               a = mips.ABEQ
+
+       case OGE_ | gc.TFLOAT32, // ACMPGEF
+               OGE_ | gc.TFLOAT64: // ACMPGED
+               a = mips.ABFPT
 
        case OAS_ | gc.TBOOL,
                OAS_ | gc.TINT8:
-               a = ppc64.AMOVB
+               a = mips.AMOVB
 
        case OAS_ | gc.TUINT8:
-               a = ppc64.AMOVBZ
+               a = mips.AMOVBU
 
        case OAS_ | gc.TINT16:
-               a = ppc64.AMOVH
+               a = mips.AMOVH
 
        case OAS_ | gc.TUINT16:
-               a = ppc64.AMOVHZ
+               a = mips.AMOVHU
 
        case OAS_ | gc.TINT32:
-               a = ppc64.AMOVW
+               a = mips.AMOVW
 
        case OAS_ | gc.TUINT32,
                OAS_ | gc.TPTR32:
-               a = ppc64.AMOVWZ
+               a = mips.AMOVWU
 
        case OAS_ | gc.TINT64,
                OAS_ | gc.TUINT64,
                OAS_ | gc.TPTR64:
-               a = ppc64.AMOVD
+               a = mips.AMOVV
 
        case OAS_ | gc.TFLOAT32:
-               a = ppc64.AFMOVS
+               a = mips.AMOVF
 
        case OAS_ | gc.TFLOAT64:
-               a = ppc64.AFMOVD
+               a = mips.AMOVD
 
        case OADD_ | gc.TINT8,
                OADD_ | gc.TUINT8,
@@ -825,17 +844,19 @@ func optoas(op gc.Op, t *gc.Type) int {
                OADD_ | gc.TUINT16,
                OADD_ | gc.TINT32,
                OADD_ | gc.TUINT32,
-               OADD_ | gc.TPTR32,
-               OADD_ | gc.TINT64,
+               OADD_ | gc.TPTR32:
+               a = mips.AADDU
+
+       case OADD_ | gc.TINT64,
                OADD_ | gc.TUINT64,
                OADD_ | gc.TPTR64:
-               a = ppc64.AADD
+               a = mips.AADDVU
 
        case OADD_ | gc.TFLOAT32:
-               a = ppc64.AFADDS
+               a = mips.AADDF
 
        case OADD_ | gc.TFLOAT64:
-               a = ppc64.AFADD
+               a = mips.AADDD
 
        case OSUB_ | gc.TINT8,
                OSUB_ | gc.TUINT8,
@@ -843,17 +864,19 @@ func optoas(op gc.Op, t *gc.Type) int {
                OSUB_ | gc.TUINT16,
                OSUB_ | gc.TINT32,
                OSUB_ | gc.TUINT32,
-               OSUB_ | gc.TPTR32,
-               OSUB_ | gc.TINT64,
+               OSUB_ | gc.TPTR32:
+               a = mips.ASUBU
+
+       case OSUB_ | gc.TINT64,
                OSUB_ | gc.TUINT64,
                OSUB_ | gc.TPTR64:
-               a = ppc64.ASUB
+               a = mips.ASUBVU
 
        case OSUB_ | gc.TFLOAT32:
-               a = ppc64.AFSUBS
+               a = mips.ASUBF
 
        case OSUB_ | gc.TFLOAT64:
-               a = ppc64.AFSUB
+               a = mips.ASUBD
 
        case OMINUS_ | gc.TINT8,
                OMINUS_ | gc.TUINT8,
@@ -865,7 +888,7 @@ func optoas(op gc.Op, t *gc.Type) int {
                OMINUS_ | gc.TINT64,
                OMINUS_ | gc.TUINT64,
                OMINUS_ | gc.TPTR64:
-               a = ppc64.ANEG
+               a = mips.ASUBVU
 
        case OAND_ | gc.TINT8,
                OAND_ | gc.TUINT8,
@@ -877,7 +900,7 @@ func optoas(op gc.Op, t *gc.Type) int {
                OAND_ | gc.TINT64,
                OAND_ | gc.TUINT64,
                OAND_ | gc.TPTR64:
-               a = ppc64.AAND
+               a = mips.AAND
 
        case OOR_ | gc.TINT8,
                OOR_ | gc.TUINT8,
@@ -889,7 +912,7 @@ func optoas(op gc.Op, t *gc.Type) int {
                OOR_ | gc.TINT64,
                OOR_ | gc.TUINT64,
                OOR_ | gc.TPTR64:
-               a = ppc64.AOR
+               a = mips.AOR
 
        case OXOR_ | gc.TINT8,
                OXOR_ | gc.TUINT8,
@@ -901,7 +924,7 @@ func optoas(op gc.Op, t *gc.Type) int {
                OXOR_ | gc.TINT64,
                OXOR_ | gc.TUINT64,
                OXOR_ | gc.TPTR64:
-               a = ppc64.AXOR
+               a = mips.AXOR
 
                // TODO(minux): handle rotates
        //case CASE(OLROT, TINT8):
@@ -927,7 +950,7 @@ func optoas(op gc.Op, t *gc.Type) int {
                OLSH_ | gc.TINT64,
                OLSH_ | gc.TUINT64,
                OLSH_ | gc.TPTR64:
-               a = ppc64.ASLD
+               a = mips.ASLLV
 
        case ORSH_ | gc.TUINT8,
                ORSH_ | gc.TUINT16,
@@ -935,13 +958,13 @@ func optoas(op gc.Op, t *gc.Type) int {
                ORSH_ | gc.TPTR32,
                ORSH_ | gc.TUINT64,
                ORSH_ | gc.TPTR64:
-               a = ppc64.ASRD
+               a = mips.ASRLV
 
        case ORSH_ | gc.TINT8,
                ORSH_ | gc.TINT16,
                ORSH_ | gc.TINT32,
                ORSH_ | gc.TINT64:
-               a = ppc64.ASRAD
+               a = mips.ASRAV
 
                // TODO(minux): handle rotates
        //case CASE(ORROTC, TINT8):
@@ -956,39 +979,37 @@ func optoas(op gc.Op, t *gc.Type) int {
        //      break;
 
        case OHMUL_ | gc.TINT64:
-               a = ppc64.AMULHD
+               a = mips.AMULV
 
        case OHMUL_ | gc.TUINT64,
                OHMUL_ | gc.TPTR64:
-               a = ppc64.AMULHDU
+               a = mips.AMULVU
 
        case OMUL_ | gc.TINT8,
                OMUL_ | gc.TINT16,
                OMUL_ | gc.TINT32,
                OMUL_ | gc.TINT64:
-               a = ppc64.AMULLD
+               a = mips.AMULV
 
        case OMUL_ | gc.TUINT8,
                OMUL_ | gc.TUINT16,
                OMUL_ | gc.TUINT32,
                OMUL_ | gc.TPTR32,
-               // don't use word multiply, the high 32-bit are undefined.
                OMUL_ | gc.TUINT64,
                OMUL_ | gc.TPTR64:
-               // for 64-bit multiplies, signedness doesn't matter.
-               a = ppc64.AMULLD
+               a = mips.AMULVU
 
        case OMUL_ | gc.TFLOAT32:
-               a = ppc64.AFMULS
+               a = mips.AMULF
 
        case OMUL_ | gc.TFLOAT64:
-               a = ppc64.AFMUL
+               a = mips.AMULD
 
        case ODIV_ | gc.TINT8,
                ODIV_ | gc.TINT16,
                ODIV_ | gc.TINT32,
                ODIV_ | gc.TINT64:
-               a = ppc64.ADIVD
+               a = mips.ADIVV
 
        case ODIV_ | gc.TUINT8,
                ODIV_ | gc.TUINT16,
@@ -996,13 +1017,13 @@ func optoas(op gc.Op, t *gc.Type) int {
                ODIV_ | gc.TPTR32,
                ODIV_ | gc.TUINT64,
                ODIV_ | gc.TPTR64:
-               a = ppc64.ADIVDU
+               a = mips.ADIVVU
 
        case ODIV_ | gc.TFLOAT32:
-               a = ppc64.AFDIVS
+               a = mips.ADIVF
 
        case ODIV_ | gc.TFLOAT64:
-               a = ppc64.AFDIV
+               a = mips.ADIVD
        }
 
        return a
diff --git a/src/cmd/compile/internal/mips64/opt.go b/src/cmd/compile/internal/mips64/opt.go
deleted file mode 100644 (file)
index 1704f63..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ppc64
-
-// Many Power ISA arithmetic and logical instructions come in four
-// standard variants.  These bits let us map between variants.
-const (
-       V_CC = 1 << 0 // xCC (affect CR field 0 flags)
-       V_V  = 1 << 1 // xV (affect SO and OV flags)
-)
index 9c3f1edb307f28ffc868b7f93098f812303f8587..681a31c0411ce2268c3941baebee4aeb12184a59 100644 (file)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
        "fmt"
 )
 
@@ -64,11 +64,11 @@ loop1:
                // can eliminate moves that don't care without
                // breaking moves that do care.  This might let us
                // simplify or remove the next peep loop, too.
-               if p.As == ppc64.AMOVD || p.As == ppc64.AFMOVD {
+               if p.As == mips.AMOVV || p.As == mips.AMOVF || p.As == mips.AMOVD {
                        if regtyp(&p.To) {
                                // Try to eliminate reg->reg moves
                                if regtyp(&p.From) {
-                                       if p.From.Type == p.To.Type {
+                                       if isfreg(&p.From) == isfreg(&p.To) {
                                                if copyprop(r) {
                                                        excise(r)
                                                        t++
@@ -82,9 +82,9 @@ loop1:
                                // Convert uses to $0 to uses of R0 and
                                // propagate R0
                                if regzer(&p.From) != 0 {
-                                       if p.To.Type == obj.TYPE_REG {
+                                       if p.To.Type == obj.TYPE_REG && !isfreg(&p.To) {
                                                p.From.Type = obj.TYPE_REG
-                                               p.From.Reg = ppc64.REGZERO
+                                               p.From.Reg = mips.REGZERO
                                                if copyprop(r) {
                                                        excise(r)
                                                        t++
@@ -113,12 +113,12 @@ loop1:
                default:
                        continue
 
-               case ppc64.AMOVH,
-                       ppc64.AMOVHZ,
-                       ppc64.AMOVB,
-                       ppc64.AMOVBZ,
-                       ppc64.AMOVW,
-                       ppc64.AMOVWZ:
+               case mips.AMOVH,
+                       mips.AMOVHU,
+                       mips.AMOVB,
+                       mips.AMOVBU,
+                       mips.AMOVW,
+                       mips.AMOVWU:
                        if p.To.Type != obj.TYPE_REG {
                                continue
                        }
@@ -141,209 +141,6 @@ loop1:
                excise(r1)
        }
 
-       if gc.Debug['D'] > 1 {
-               goto ret /* allow following code improvement to be suppressed */
-       }
-
-       /*
-        * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
-        * when OP can set condition codes correctly
-        */
-       for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
-               p = r.Prog
-               switch p.As {
-               case ppc64.ACMP,
-                       ppc64.ACMPW: /* always safe? */
-                       if regzer(&p.To) == 0 {
-                               continue
-                       }
-                       r1 = r.S1
-                       if r1 == nil {
-                               continue
-                       }
-                       switch r1.Prog.As {
-                       default:
-                               continue
-
-                               /* the conditions can be complex and these are currently little used */
-                       case ppc64.ABCL,
-                               ppc64.ABC:
-                               continue
-
-                       case ppc64.ABEQ,
-                               ppc64.ABGE,
-                               ppc64.ABGT,
-                               ppc64.ABLE,
-                               ppc64.ABLT,
-                               ppc64.ABNE,
-                               ppc64.ABVC,
-                               ppc64.ABVS:
-                               break
-                       }
-
-                       r1 = r
-                       for {
-                               r1 = gc.Uniqp(r1)
-                               if r1 == nil || r1.Prog.As != obj.ANOP {
-                                       break
-                               }
-                       }
-
-                       if r1 == nil {
-                               continue
-                       }
-                       p1 = r1.Prog
-                       if p1.To.Type != obj.TYPE_REG || p1.To.Reg != p.From.Reg {
-                               continue
-                       }
-                       switch p1.As {
-                       /* irregular instructions */
-                       case ppc64.ASUB,
-                               ppc64.AADD,
-                               ppc64.AXOR,
-                               ppc64.AOR:
-                               if p1.From.Type == obj.TYPE_CONST || p1.From.Type == obj.TYPE_ADDR {
-                                       continue
-                               }
-                       }
-
-                       switch p1.As {
-                       default:
-                               continue
-
-                       case ppc64.AMOVW,
-                               ppc64.AMOVD:
-                               if p1.From.Type != obj.TYPE_REG {
-                                       continue
-                               }
-                               continue
-
-                       case ppc64.AANDCC,
-                               ppc64.AANDNCC,
-                               ppc64.AORCC,
-                               ppc64.AORNCC,
-                               ppc64.AXORCC,
-                               ppc64.ASUBCC,
-                               ppc64.ASUBECC,
-                               ppc64.ASUBMECC,
-                               ppc64.ASUBZECC,
-                               ppc64.AADDCC,
-                               ppc64.AADDCCC,
-                               ppc64.AADDECC,
-                               ppc64.AADDMECC,
-                               ppc64.AADDZECC,
-                               ppc64.ARLWMICC,
-                               ppc64.ARLWNMCC,
-                               /* don't deal with floating point instructions for now */
-                               /*
-                                       case AFABS:
-                                       case AFADD:
-                                       case AFADDS:
-                                       case AFCTIW:
-                                       case AFCTIWZ:
-                                       case AFDIV:
-                                       case AFDIVS:
-                                       case AFMADD:
-                                       case AFMADDS:
-                                       case AFMOVD:
-                                       case AFMSUB:
-                                       case AFMSUBS:
-                                       case AFMUL:
-                                       case AFMULS:
-                                       case AFNABS:
-                                       case AFNEG:
-                                       case AFNMADD:
-                                       case AFNMADDS:
-                                       case AFNMSUB:
-                                       case AFNMSUBS:
-                                       case AFRSP:
-                                       case AFSUB:
-                                       case AFSUBS:
-                                       case ACNTLZW:
-                                       case AMTFSB0:
-                                       case AMTFSB1:
-                               */
-                               ppc64.AADD,
-                               ppc64.AADDV,
-                               ppc64.AADDC,
-                               ppc64.AADDCV,
-                               ppc64.AADDME,
-                               ppc64.AADDMEV,
-                               ppc64.AADDE,
-                               ppc64.AADDEV,
-                               ppc64.AADDZE,
-                               ppc64.AADDZEV,
-                               ppc64.AAND,
-                               ppc64.AANDN,
-                               ppc64.ADIVW,
-                               ppc64.ADIVWV,
-                               ppc64.ADIVWU,
-                               ppc64.ADIVWUV,
-                               ppc64.ADIVD,
-                               ppc64.ADIVDV,
-                               ppc64.ADIVDU,
-                               ppc64.ADIVDUV,
-                               ppc64.AEQV,
-                               ppc64.AEXTSB,
-                               ppc64.AEXTSH,
-                               ppc64.AEXTSW,
-                               ppc64.AMULHW,
-                               ppc64.AMULHWU,
-                               ppc64.AMULLW,
-                               ppc64.AMULLWV,
-                               ppc64.AMULHD,
-                               ppc64.AMULHDU,
-                               ppc64.AMULLD,
-                               ppc64.AMULLDV,
-                               ppc64.ANAND,
-                               ppc64.ANEG,
-                               ppc64.ANEGV,
-                               ppc64.ANOR,
-                               ppc64.AOR,
-                               ppc64.AORN,
-                               ppc64.AREM,
-                               ppc64.AREMV,
-                               ppc64.AREMU,
-                               ppc64.AREMUV,
-                               ppc64.AREMD,
-                               ppc64.AREMDV,
-                               ppc64.AREMDU,
-                               ppc64.AREMDUV,
-                               ppc64.ARLWMI,
-                               ppc64.ARLWNM,
-                               ppc64.ASLW,
-                               ppc64.ASRAW,
-                               ppc64.ASRW,
-                               ppc64.ASLD,
-                               ppc64.ASRAD,
-                               ppc64.ASRD,
-                               ppc64.ASUB,
-                               ppc64.ASUBV,
-                               ppc64.ASUBC,
-                               ppc64.ASUBCV,
-                               ppc64.ASUBME,
-                               ppc64.ASUBMEV,
-                               ppc64.ASUBE,
-                               ppc64.ASUBEV,
-                               ppc64.ASUBZE,
-                               ppc64.ASUBZEV,
-                               ppc64.AXOR:
-                               t = variant2as(int(p1.As), as2variant(int(p1.As))|V_CC)
-                       }
-
-                       if gc.Debug['D'] != 0 {
-                               fmt.Printf("cmp %v; %v -> ", p1, p)
-                       }
-                       p1.As = int16(t)
-                       if gc.Debug['D'] != 0 {
-                               fmt.Printf("%v\n", p1)
-                       }
-                       excise(r)
-                       continue
-               }
-       }
-
-ret:
        gc.Flowend(g)
 }
 
@@ -368,7 +165,7 @@ func regzer(a *obj.Addr) int {
                }
        }
        if a.Type == obj.TYPE_REG {
-               if a.Reg == ppc64.REGZERO {
+               if a.Reg == mips.REGZERO {
                        return 1
                }
        }
@@ -377,7 +174,11 @@ func regzer(a *obj.Addr) int {
 
 func regtyp(a *obj.Addr) bool {
        // TODO(rsc): Floating point register exclusions?
-       return a.Type == obj.TYPE_REG && ppc64.REG_R0 <= a.Reg && a.Reg <= ppc64.REG_F31 && a.Reg != ppc64.REGZERO
+       return a.Type == obj.TYPE_REG && mips.REG_R0 <= a.Reg && a.Reg <= mips.REG_F31 && a.Reg != mips.REGZERO
+}
+
+func isfreg(a *obj.Addr) bool {
+       return mips.REG_F0 <= a.Reg && a.Reg <= mips.REG_F31
 }
 
 /*
@@ -607,7 +408,7 @@ func copy1(v1 *obj.Addr, v2 *obj.Addr, r *gc.Flow, f int) bool {
 //     0 otherwise (not touched)
 func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
        if p.From3Type() != obj.TYPE_NONE {
-               // 9g never generates a from3
+               // never generates a from3
                fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
        }
 
@@ -617,34 +418,29 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
                return 2
 
        case obj.ANOP, /* read p->from, write p->to */
-               ppc64.AMOVH,
-               ppc64.AMOVHZ,
-               ppc64.AMOVB,
-               ppc64.AMOVBZ,
-               ppc64.AMOVW,
-               ppc64.AMOVWZ,
-               ppc64.AMOVD,
-               ppc64.ANEG,
-               ppc64.ANEGCC,
-               ppc64.AADDME,
-               ppc64.AADDMECC,
-               ppc64.AADDZE,
-               ppc64.AADDZECC,
-               ppc64.ASUBME,
-               ppc64.ASUBMECC,
-               ppc64.ASUBZE,
-               ppc64.ASUBZECC,
-               ppc64.AFCTIW,
-               ppc64.AFCTIWZ,
-               ppc64.AFCTID,
-               ppc64.AFCTIDZ,
-               ppc64.AFCFID,
-               ppc64.AFCFIDCC,
-               ppc64.AFMOVS,
-               ppc64.AFMOVD,
-               ppc64.AFRSP,
-               ppc64.AFNEG,
-               ppc64.AFNEGCC:
+               mips.AMOVV,
+               mips.AMOVF,
+               mips.AMOVD,
+               mips.AMOVH,
+               mips.AMOVHU,
+               mips.AMOVB,
+               mips.AMOVBU,
+               mips.AMOVW,
+               mips.AMOVWU,
+               mips.AMOVFD,
+               mips.AMOVDF,
+               mips.AMOVDW,
+               mips.AMOVWD,
+               mips.AMOVFW,
+               mips.AMOVWF,
+               mips.AMOVDV,
+               mips.AMOVVD,
+               mips.AMOVFV,
+               mips.AMOVVF,
+               mips.ATRUNCFV,
+               mips.ATRUNCDV,
+               mips.ATRUNCFW,
+               mips.ATRUNCDW:
                if s != nil {
                        if copysub(&p.From, v, s, 1) != 0 {
                                return 1
@@ -680,103 +476,37 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 
                return 0
 
-       case ppc64.AMOVBU, /* rar p->from, write p->to or read p->from, rar p->to */
-               ppc64.AMOVBZU,
-               ppc64.AMOVHU,
-               ppc64.AMOVHZU,
-               ppc64.AMOVWZU,
-               ppc64.AMOVDU:
-               if p.From.Type == obj.TYPE_MEM {
-                       if copyas(&p.From, v) {
-                               // No s!=nil check; need to fail
-                               // anyway in that case
-                               return 2
-                       }
-
-                       if s != nil {
-                               if copysub(&p.To, v, s, 1) != 0 {
-                                       return 1
-                               }
-                               return 0
-                       }
-
-                       if copyas(&p.To, v) {
-                               return 3
-                       }
-               } else if p.To.Type == obj.TYPE_MEM {
-                       if copyas(&p.To, v) {
-                               return 2
-                       }
-                       if s != nil {
-                               if copysub(&p.From, v, s, 1) != 0 {
-                                       return 1
-                               }
-                               return 0
-                       }
-
-                       if copyau(&p.From, v) {
-                               return 1
-                       }
-               } else {
-                       fmt.Printf("copyu: bad %v\n", p)
-               }
-
-               return 0
-
-       case ppc64.ARLWMI, /* read p->from, read p->reg, rar p->to */
-               ppc64.ARLWMICC:
-               if copyas(&p.To, v) {
-                       return 2
-               }
-               fallthrough
-
-               /* fall through */
-       case ppc64.AADD,
-               /* read p->from, read p->reg, write p->to */
-               ppc64.AADDC,
-               ppc64.AADDE,
-               ppc64.ASUB,
-               ppc64.ASLW,
-               ppc64.ASRW,
-               ppc64.ASRAW,
-               ppc64.ASLD,
-               ppc64.ASRD,
-               ppc64.ASRAD,
-               ppc64.AOR,
-               ppc64.AORCC,
-               ppc64.AORN,
-               ppc64.AORNCC,
-               ppc64.AAND,
-               ppc64.AANDCC,
-               ppc64.AANDN,
-               ppc64.AANDNCC,
-               ppc64.ANAND,
-               ppc64.ANANDCC,
-               ppc64.ANOR,
-               ppc64.ANORCC,
-               ppc64.AXOR,
-               ppc64.AMULHW,
-               ppc64.AMULHWU,
-               ppc64.AMULLW,
-               ppc64.AMULLD,
-               ppc64.ADIVW,
-               ppc64.ADIVD,
-               ppc64.ADIVWU,
-               ppc64.ADIVDU,
-               ppc64.AREM,
-               ppc64.AREMU,
-               ppc64.AREMD,
-               ppc64.AREMDU,
-               ppc64.ARLWNM,
-               ppc64.ARLWNMCC,
-               ppc64.AFADDS,
-               ppc64.AFADD,
-               ppc64.AFSUBS,
-               ppc64.AFSUB,
-               ppc64.AFMULS,
-               ppc64.AFMUL,
-               ppc64.AFDIVS,
-               ppc64.AFDIV:
+       case mips.ASGT, /* read p->from, read p->reg, write p->to */
+               mips.ASGTU,
+
+               mips.AADD,
+               mips.AADDU,
+               mips.ASUB,
+               mips.ASUBU,
+               mips.ASLL,
+               mips.ASRL,
+               mips.ASRA,
+               mips.AOR,
+               mips.ANOR,
+               mips.AAND,
+               mips.AXOR,
+
+               mips.AADDV,
+               mips.AADDVU,
+               mips.ASUBV,
+               mips.ASUBVU,
+               mips.ASLLV,
+               mips.ASRLV,
+               mips.ASRAV,
+
+               mips.AADDF,
+               mips.AADDD,
+               mips.ASUBF,
+               mips.ASUBD,
+               mips.AMULF,
+               mips.AMULD,
+               mips.ADIVF,
+               mips.ADIVD:
                if s != nil {
                        if copysub(&p.From, v, s, 1) != 0 {
                                return 1
@@ -822,42 +552,47 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
                }
                return 0
 
-       case ppc64.ABEQ,
-               ppc64.ABGT,
-               ppc64.ABGE,
-               ppc64.ABLT,
-               ppc64.ABLE,
-               ppc64.ABNE,
-               ppc64.ABVC,
-               ppc64.ABVS:
-               return 0
-
        case obj.ACHECKNIL, /* read p->from */
-               ppc64.ACMP, /* read p->from, read p->to */
-               ppc64.ACMPU,
-               ppc64.ACMPW,
-               ppc64.ACMPWU,
-               ppc64.AFCMPO,
-               ppc64.AFCMPU:
+               mips.ABEQ, /* read p->from, read p->reg */
+               mips.ABNE,
+               mips.ABGTZ,
+               mips.ABGEZ,
+               mips.ABLTZ,
+               mips.ABLEZ,
+
+               mips.ACMPEQD,
+               mips.ACMPEQF,
+               mips.ACMPGED,
+               mips.ACMPGEF,
+               mips.ACMPGTD,
+               mips.ACMPGTF,
+               mips.ABFPF,
+               mips.ABFPT,
+
+               mips.AMUL,
+               mips.AMULU,
+               mips.ADIV,
+               mips.ADIVU,
+               mips.AMULV,
+               mips.AMULVU,
+               mips.ADIVV,
+               mips.ADIVVU:
                if s != nil {
                        if copysub(&p.From, v, s, 1) != 0 {
                                return 1
                        }
-                       return copysub(&p.To, v, s, 1)
+                       return copysub1(p, v, s, 1)
                }
 
                if copyau(&p.From, v) {
                        return 1
                }
-               if copyau(&p.To, v) {
+               if copyau1(p, v) {
                        return 1
                }
                return 0
 
-               // 9g never generates a branch to a GPR (this isn't
-       // even a normal instruction; liblink turns it in to a
-       // mov and a branch).
-       case ppc64.ABR: /* read p->to */
+       case mips.AJMP: /* read p->to */
                if s != nil {
                        if copysub(&p.To, v, s, 1) != 0 {
                                return 1
@@ -870,7 +605,7 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
                }
                return 0
 
-       case obj.ARET: /* funny */
+       case mips.ARET: /* funny */
                if s != nil {
                        return 0
                }
@@ -879,20 +614,20 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
                // everything is set (and not used).
                return 3
 
-       case ppc64.ABL: /* funny */
+       case mips.AJAL: /* funny */
                if v.Type == obj.TYPE_REG {
                        // TODO(rsc): REG_R0 and REG_F0 used to be
                        // (when register numbers started at 0) exregoffset and exfregoffset,
                        // which are unset entirely.
                        // It's strange that this handles R0 and F0 differently from the other
                        // registers. Possible failure to optimize?
-                       if ppc64.REG_R0 < v.Reg && v.Reg <= ppc64.REGEXT {
+                       if mips.REG_R0 < v.Reg && v.Reg <= mips.REG_R31 {
                                return 2
                        }
-                       if v.Reg == ppc64.REGARG {
+                       if v.Reg == mips.REGARG {
                                return 2
                        }
-                       if ppc64.REG_F0 < v.Reg && v.Reg <= ppc64.FREGEXT {
+                       if mips.REG_F0 < v.Reg && v.Reg <= mips.REG_F31 {
                                return 2
                        }
                }
@@ -913,28 +648,28 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
                }
                return 3
 
-               // R0 is zero, used by DUFFZERO, cannot be substituted.
-       // R3 is ptr to memory, used and set, cannot be substituted.
+       // R0 is zero, used by DUFFZERO, cannot be substituted.
+       // R1 is ptr to memory, used and set, cannot be substituted.
        case obj.ADUFFZERO:
                if v.Type == obj.TYPE_REG {
                        if v.Reg == 0 {
                                return 1
                        }
-                       if v.Reg == 3 {
+                       if v.Reg == 1 {
                                return 2
                        }
                }
 
                return 0
 
-               // R3, R4 are ptr to src, dst, used and set, cannot be substituted.
-       // R5 is scratch, set by DUFFCOPY, cannot be substituted.
+       // R1, R2 are ptr to src, dst, used and set, cannot be substituted.
+       // R3 is scratch, set by DUFFCOPY, cannot be substituted.
        case obj.ADUFFCOPY:
                if v.Type == obj.TYPE_REG {
-                       if v.Reg == 3 || v.Reg == 4 {
+                       if v.Reg == 1 || v.Reg == 2 {
                                return 2
                        }
-                       if v.Reg == 5 {
+                       if v.Reg == 3 {
                                return 3
                        }
                }
@@ -943,7 +678,7 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 
        case obj.ATEXT: /* funny */
                if v.Type == obj.TYPE_REG {
-                       if v.Reg == ppc64.REGARG {
+                       if v.Reg == mips.REGARG {
                                return 3
                        }
                }
@@ -1006,7 +741,7 @@ func copyau1(p *obj.Prog, v *obj.Addr) bool {
 }
 
 // copysub replaces v with s in a if f!=0 or indicates it if could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
+// Returns 1 on failure to substitute (it always succeeds on mips).
 func copysub(a *obj.Addr, v *obj.Addr, s *obj.Addr, f int) int {
        if f != 0 {
                if copyau(a, v) {
@@ -1017,7 +752,7 @@ func copysub(a *obj.Addr, v *obj.Addr, s *obj.Addr, f int) int {
 }
 
 // copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
+// Returns 1 on failure to substitute (it always succeeds on mips).
 func copysub1(p1 *obj.Prog, v *obj.Addr, s *obj.Addr, f int) int {
        if f != 0 {
                if copyau1(p1, v) {
@@ -1047,5 +782,5 @@ func smallindir(a *obj.Addr, reg *obj.Addr) bool {
 }
 
 func stackaddr(a *obj.Addr) bool {
-       return a.Type == obj.TYPE_REG && a.Reg == ppc64.REGSP
+       return a.Type == obj.TYPE_REG && a.Reg == mips.REGSP
 }
index 9b8719bd8f40e94bcff2b356a51e8124c30f4571..bf13d82a373c873f0927c9c28711813b9cafc99d 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package ppc64
+package mips64
 
 import (
        "cmd/compile/internal/gc"
        "cmd/internal/obj"
-       "cmd/internal/obj/ppc64"
+       "cmd/internal/obj/mips"
 )
 
 const (
@@ -24,7 +24,7 @@ const (
 // size variants of an operation even if we just use a subset.
 //
 // The table is formatted for 8-space tabs.
-var progtable = [ppc64.ALAST]obj.ProgInfo{
+var progtable = [mips.ALAST]obj.ProgInfo{
        obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
        obj.ATEXT:     {Flags: gc.Pseudo},
        obj.AFUNCDATA: {Flags: gc.Pseudo},
@@ -36,106 +36,105 @@ var progtable = [ppc64.ALAST]obj.ProgInfo{
        obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
 
        // NOP is an internal no-op that also stands
-       // for USED and SET annotations, not the Power opcode.
+       // for USED and SET annotations, not the MIPS opcode.
        obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
 
        // Integer
-       ppc64.AADD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ASUB:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ANEG:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AAND:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AOR:     {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AXOR:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AMULLD:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AMULLW:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AMULHD:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AMULHDU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ADIVD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ADIVDU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ASLD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ASRD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ASRAD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.ACMP:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-       ppc64.ACMPU:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
-       ppc64.ATD:     {Flags: gc.SizeQ | gc.RightRead},
+       mips.AADD:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AADDU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AADDV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AADDVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUB:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUBU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUBV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUBVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AAND:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AOR:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AXOR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ANOR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AMUL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.AMULU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.AMULV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.AMULVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.ADIV:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.ADIVU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.ADIVV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.ADIVVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.AREM:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.AREMU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+       mips.AREMV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.AREMVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+       mips.ASLL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASLLV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASRA:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASRAV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASRL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASRLV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASGT:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASGTU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
 
        // Floating point.
-       ppc64.AFADD:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFADDS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFSUB:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFSUBS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFMUL:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFMULS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFDIV:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFDIVS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFCTIDZ: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFCFID:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
-       ppc64.AFCMPU:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
-       ppc64.AFRSP:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AADDF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AADDD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUBF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ASUBD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AMULF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AMULD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ADIVF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.ADIVD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+       mips.AABSF:    {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+       mips.AABSD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+       mips.ANEGF:    {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+       mips.ANEGD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+       mips.ACMPEQF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+       mips.ACMPEQD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+       mips.ACMPGTF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+       mips.ACMPGTD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+       mips.ACMPGEF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+       mips.ACMPGED:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+       mips.AMOVFD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVDF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVFW:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVWF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVDW:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVWD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVFV:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVVF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVDV:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.AMOVVD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.ATRUNCFW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.ATRUNCDW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.ATRUNCFV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+       mips.ATRUNCDV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
 
        // Moves
-       ppc64.AMOVB:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
-       ppc64.AMOVBZ: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AMOVH:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
-       ppc64.AMOVHZ: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AMOVW:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-
-       // there is no AMOVWU.
-       ppc64.AMOVWZU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
-       ppc64.AMOVWZ:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AMOVD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
-       ppc64.AMOVDU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
-       ppc64.AFMOVS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
-       ppc64.AFMOVD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+       mips.AMOVB:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVH:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVW:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVWU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+       mips.AMOVF:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+       mips.AMOVD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
 
        // Jumps
-       ppc64.ABR:     {Flags: gc.Jump | gc.Break},
-       ppc64.ABL:     {Flags: gc.Call},
-       ppc64.ABEQ:    {Flags: gc.Cjmp},
-       ppc64.ABNE:    {Flags: gc.Cjmp},
-       ppc64.ABGE:    {Flags: gc.Cjmp},
-       ppc64.ABLT:    {Flags: gc.Cjmp},
-       ppc64.ABGT:    {Flags: gc.Cjmp},
-       ppc64.ABLE:    {Flags: gc.Cjmp},
-       obj.ARET:      {Flags: gc.Break},
+       mips.AJMP:     {Flags: gc.Jump | gc.Break},
+       mips.AJAL:     {Flags: gc.Call},
+       mips.ABEQ:     {Flags: gc.Cjmp},
+       mips.ABNE:     {Flags: gc.Cjmp},
+       mips.ABGEZ:    {Flags: gc.Cjmp},
+       mips.ABLTZ:    {Flags: gc.Cjmp},
+       mips.ABGTZ:    {Flags: gc.Cjmp},
+       mips.ABLEZ:    {Flags: gc.Cjmp},
+       mips.ABFPF:    {Flags: gc.Cjmp},
+       mips.ABFPT:    {Flags: gc.Cjmp},
+       mips.ARET:     {Flags: gc.Break},
        obj.ADUFFZERO: {Flags: gc.Call},
        obj.ADUFFCOPY: {Flags: gc.Call},
 }
 
-var initproginfo_initialized int
-
-func initproginfo() {
-       var addvariant = []int{V_CC, V_V, V_CC | V_V}
-
-       if initproginfo_initialized != 0 {
-               return
-       }
-       initproginfo_initialized = 1
-
-       // Perform one-time expansion of instructions in progtable to
-       // their CC, V, and VCC variants
-       var as2 int
-       var i int
-       var variant int
-       for as := int(0); as < len(progtable); as++ {
-               if progtable[as].Flags == 0 {
-                       continue
-               }
-               variant = as2variant(as)
-               for i = 0; i < len(addvariant); i++ {
-                       as2 = variant2as(as, variant|addvariant[i])
-                       if as2 != 0 && progtable[as2].Flags == 0 {
-                               progtable[as2] = progtable[as]
-                       }
-               }
-       }
-}
-
 func proginfo(p *obj.Prog) {
-       initproginfo()
-
        info := &p.Info
        *info = progtable[p.As]
        if info.Flags == 0 {
@@ -149,16 +148,10 @@ func proginfo(p *obj.Prog) {
 
        if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
                info.Regindex |= RtoB(int(p.From.Reg))
-               if info.Flags&gc.PostInc != 0 {
-                       info.Regset |= RtoB(int(p.From.Reg))
-               }
        }
 
        if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
                info.Regindex |= RtoB(int(p.To.Reg))
-               if info.Flags&gc.PostInc != 0 {
-                       info.Regset |= RtoB(int(p.To.Reg))
-               }
        }
 
        if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
@@ -167,148 +160,14 @@ func proginfo(p *obj.Prog) {
        }
 
        if p.As == obj.ADUFFZERO {
-               info.Reguse |= 1<<0 | RtoB(ppc64.REG_R3)
-               info.Regset |= RtoB(ppc64.REG_R3)
+               info.Reguse |= 1<<0 | RtoB(mips.REGRT1)
+               info.Regset |= RtoB(mips.REGRT1)
        }
 
        if p.As == obj.ADUFFCOPY {
                // TODO(austin) Revisit when duffcopy is implemented
-               info.Reguse |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4) | RtoB(ppc64.REG_R5)
-
-               info.Regset |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4)
-       }
-}
+               info.Reguse |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2) | RtoB(mips.REG_R3)
 
-// Instruction variants table.  Initially this contains entries only
-// for the "base" form of each instruction.  On the first call to
-// as2variant or variant2as, we'll add the variants to the table.
-var varianttable = [ppc64.ALAST][4]int{
-       ppc64.AADD:     [4]int{ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC},
-       ppc64.AADDC:    [4]int{ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC},
-       ppc64.AADDE:    [4]int{ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC},
-       ppc64.AADDME:   [4]int{ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC},
-       ppc64.AADDZE:   [4]int{ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC},
-       ppc64.AAND:     [4]int{ppc64.AAND, ppc64.AANDCC, 0, 0},
-       ppc64.AANDN:    [4]int{ppc64.AANDN, ppc64.AANDNCC, 0, 0},
-       ppc64.ACNTLZD:  [4]int{ppc64.ACNTLZD, ppc64.ACNTLZDCC, 0, 0},
-       ppc64.ACNTLZW:  [4]int{ppc64.ACNTLZW, ppc64.ACNTLZWCC, 0, 0},
-       ppc64.ADIVD:    [4]int{ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC},
-       ppc64.ADIVDU:   [4]int{ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC},
-       ppc64.ADIVW:    [4]int{ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC},
-       ppc64.ADIVWU:   [4]int{ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC},
-       ppc64.AEQV:     [4]int{ppc64.AEQV, ppc64.AEQVCC, 0, 0},
-       ppc64.AEXTSB:   [4]int{ppc64.AEXTSB, ppc64.AEXTSBCC, 0, 0},
-       ppc64.AEXTSH:   [4]int{ppc64.AEXTSH, ppc64.AEXTSHCC, 0, 0},
-       ppc64.AEXTSW:   [4]int{ppc64.AEXTSW, ppc64.AEXTSWCC, 0, 0},
-       ppc64.AFABS:    [4]int{ppc64.AFABS, ppc64.AFABSCC, 0, 0},
-       ppc64.AFADD:    [4]int{ppc64.AFADD, ppc64.AFADDCC, 0, 0},
-       ppc64.AFADDS:   [4]int{ppc64.AFADDS, ppc64.AFADDSCC, 0, 0},
-       ppc64.AFCFID:   [4]int{ppc64.AFCFID, ppc64.AFCFIDCC, 0, 0},
-       ppc64.AFCTID:   [4]int{ppc64.AFCTID, ppc64.AFCTIDCC, 0, 0},
-       ppc64.AFCTIDZ:  [4]int{ppc64.AFCTIDZ, ppc64.AFCTIDZCC, 0, 0},
-       ppc64.AFCTIW:   [4]int{ppc64.AFCTIW, ppc64.AFCTIWCC, 0, 0},
-       ppc64.AFCTIWZ:  [4]int{ppc64.AFCTIWZ, ppc64.AFCTIWZCC, 0, 0},
-       ppc64.AFDIV:    [4]int{ppc64.AFDIV, ppc64.AFDIVCC, 0, 0},
-       ppc64.AFDIVS:   [4]int{ppc64.AFDIVS, ppc64.AFDIVSCC, 0, 0},
-       ppc64.AFMADD:   [4]int{ppc64.AFMADD, ppc64.AFMADDCC, 0, 0},
-       ppc64.AFMADDS:  [4]int{ppc64.AFMADDS, ppc64.AFMADDSCC, 0, 0},
-       ppc64.AFMOVD:   [4]int{ppc64.AFMOVD, ppc64.AFMOVDCC, 0, 0},
-       ppc64.AFMSUB:   [4]int{ppc64.AFMSUB, ppc64.AFMSUBCC, 0, 0},
-       ppc64.AFMSUBS:  [4]int{ppc64.AFMSUBS, ppc64.AFMSUBSCC, 0, 0},
-       ppc64.AFMUL:    [4]int{ppc64.AFMUL, ppc64.AFMULCC, 0, 0},
-       ppc64.AFMULS:   [4]int{ppc64.AFMULS, ppc64.AFMULSCC, 0, 0},
-       ppc64.AFNABS:   [4]int{ppc64.AFNABS, ppc64.AFNABSCC, 0, 0},
-       ppc64.AFNEG:    [4]int{ppc64.AFNEG, ppc64.AFNEGCC, 0, 0},
-       ppc64.AFNMADD:  [4]int{ppc64.AFNMADD, ppc64.AFNMADDCC, 0, 0},
-       ppc64.AFNMADDS: [4]int{ppc64.AFNMADDS, ppc64.AFNMADDSCC, 0, 0},
-       ppc64.AFNMSUB:  [4]int{ppc64.AFNMSUB, ppc64.AFNMSUBCC, 0, 0},
-       ppc64.AFNMSUBS: [4]int{ppc64.AFNMSUBS, ppc64.AFNMSUBSCC, 0, 0},
-       ppc64.AFRES:    [4]int{ppc64.AFRES, ppc64.AFRESCC, 0, 0},
-       ppc64.AFRSP:    [4]int{ppc64.AFRSP, ppc64.AFRSPCC, 0, 0},
-       ppc64.AFRSQRTE: [4]int{ppc64.AFRSQRTE, ppc64.AFRSQRTECC, 0, 0},
-       ppc64.AFSEL:    [4]int{ppc64.AFSEL, ppc64.AFSELCC, 0, 0},
-       ppc64.AFSQRT:   [4]int{ppc64.AFSQRT, ppc64.AFSQRTCC, 0, 0},
-       ppc64.AFSQRTS:  [4]int{ppc64.AFSQRTS, ppc64.AFSQRTSCC, 0, 0},
-       ppc64.AFSUB:    [4]int{ppc64.AFSUB, ppc64.AFSUBCC, 0, 0},
-       ppc64.AFSUBS:   [4]int{ppc64.AFSUBS, ppc64.AFSUBSCC, 0, 0},
-       ppc64.AMTFSB0:  [4]int{ppc64.AMTFSB0, ppc64.AMTFSB0CC, 0, 0},
-       ppc64.AMTFSB1:  [4]int{ppc64.AMTFSB1, ppc64.AMTFSB1CC, 0, 0},
-       ppc64.AMULHD:   [4]int{ppc64.AMULHD, ppc64.AMULHDCC, 0, 0},
-       ppc64.AMULHDU:  [4]int{ppc64.AMULHDU, ppc64.AMULHDUCC, 0, 0},
-       ppc64.AMULHW:   [4]int{ppc64.AMULHW, ppc64.AMULHWCC, 0, 0},
-       ppc64.AMULHWU:  [4]int{ppc64.AMULHWU, ppc64.AMULHWUCC, 0, 0},
-       ppc64.AMULLD:   [4]int{ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC},
-       ppc64.AMULLW:   [4]int{ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC},
-       ppc64.ANAND:    [4]int{ppc64.ANAND, ppc64.ANANDCC, 0, 0},
-       ppc64.ANEG:     [4]int{ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC},
-       ppc64.ANOR:     [4]int{ppc64.ANOR, ppc64.ANORCC, 0, 0},
-       ppc64.AOR:      [4]int{ppc64.AOR, ppc64.AORCC, 0, 0},
-       ppc64.AORN:     [4]int{ppc64.AORN, ppc64.AORNCC, 0, 0},
-       ppc64.AREM:     [4]int{ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC},
-       ppc64.AREMD:    [4]int{ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC},
-       ppc64.AREMDU:   [4]int{ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC},
-       ppc64.AREMU:    [4]int{ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC},
-       ppc64.ARLDC:    [4]int{ppc64.ARLDC, ppc64.ARLDCCC, 0, 0},
-       ppc64.ARLDCL:   [4]int{ppc64.ARLDCL, ppc64.ARLDCLCC, 0, 0},
-       ppc64.ARLDCR:   [4]int{ppc64.ARLDCR, ppc64.ARLDCRCC, 0, 0},
-       ppc64.ARLDMI:   [4]int{ppc64.ARLDMI, ppc64.ARLDMICC, 0, 0},
-       ppc64.ARLWMI:   [4]int{ppc64.ARLWMI, ppc64.ARLWMICC, 0, 0},
-       ppc64.ARLWNM:   [4]int{ppc64.ARLWNM, ppc64.ARLWNMCC, 0, 0},
-       ppc64.ASLD:     [4]int{ppc64.ASLD, ppc64.ASLDCC, 0, 0},
-       ppc64.ASLW:     [4]int{ppc64.ASLW, ppc64.ASLWCC, 0, 0},
-       ppc64.ASRAD:    [4]int{ppc64.ASRAD, ppc64.ASRADCC, 0, 0},
-       ppc64.ASRAW:    [4]int{ppc64.ASRAW, ppc64.ASRAWCC, 0, 0},
-       ppc64.ASRD:     [4]int{ppc64.ASRD, ppc64.ASRDCC, 0, 0},
-       ppc64.ASRW:     [4]int{ppc64.ASRW, ppc64.ASRWCC, 0, 0},
-       ppc64.ASUB:     [4]int{ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC},
-       ppc64.ASUBC:    [4]int{ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC},
-       ppc64.ASUBE:    [4]int{ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC},
-       ppc64.ASUBME:   [4]int{ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC},
-       ppc64.ASUBZE:   [4]int{ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC},
-       ppc64.AXOR:     [4]int{ppc64.AXOR, ppc64.AXORCC, 0, 0},
-}
-
-var initvariants_initialized int
-
-func initvariants() {
-       if initvariants_initialized != 0 {
-               return
-       }
-       initvariants_initialized = 1
-
-       var j int
-       for i := int(0); i < len(varianttable); i++ {
-               if varianttable[i][0] == 0 {
-                       // Instruction has no variants
-                       varianttable[i][0] = i
-
-                       continue
-               }
-
-               // Copy base form to other variants
-               if varianttable[i][0] == i {
-                       for j = 0; j < len(varianttable[i]); j++ {
-                               varianttable[varianttable[i][j]] = varianttable[i]
-                       }
-               }
-       }
-}
-
-// as2variant returns the variant (V_*) flags of instruction as.
-func as2variant(as int) int {
-       initvariants()
-       for i := int(0); i < len(varianttable[as]); i++ {
-               if varianttable[as][i] == as {
-                       return i
-               }
+               info.Regset |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2)
        }
-       gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as))
-       return 0
-}
-
-// variant2as returns the instruction as with the given variant (V_*) flags.
-// If no such variant exists, this returns 0.
-func variant2as(as int, flags int) int {
-       initvariants()
-       return varianttable[as][flags]
 }
index fa1cb71975e511316b44887eb471989503690f6c..5c46588e07bf444ea44e8f04ade84483159ee11f 100644 (file)
@@ -28,9 +28,9 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-package ppc64
+package mips64
 
-import "cmd/internal/obj/ppc64"
+import "cmd/internal/obj/mips"
 import "cmd/compile/internal/gc"
 
 const (
@@ -111,10 +111,10 @@ func regnames(n *int) []string {
 
 func excludedregs() uint64 {
        // Exclude registers with fixed functions
-       regbits := uint64(1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS))
+       regbits := uint64(1<<0 | RtoB(mips.REGSP) | RtoB(mips.REGG) | RtoB(mips.REGTMP) | RtoB(mips.REGLINK) | RtoB(mips.REG_R26) | RtoB(mips.REG_R27))
 
        // Also exclude floating point registers with fixed constants
-       regbits |= RtoB(ppc64.REG_F27) | RtoB(ppc64.REG_F28) | RtoB(ppc64.REG_F29) | RtoB(ppc64.REG_F30) | RtoB(ppc64.REG_F31)
+       regbits |= RtoB(mips.FREGZERO) | RtoB(mips.FREGHALF) | RtoB(mips.FREGONE) | RtoB(mips.FREGTWO)
 
        return regbits
 }
@@ -136,11 +136,11 @@ func doregbits(r int) uint64 {
  *     32+31   F31
  */
 func RtoB(r int) uint64 {
-       if r > ppc64.REG_R0 && r <= ppc64.REG_R31 {
-               return 1 << uint(r-ppc64.REG_R0)
+       if r > mips.REG_R0 && r <= mips.REG_R31 {
+               return 1 << uint(r-mips.REG_R0)
        }
-       if r >= ppc64.REG_F0 && r <= ppc64.REG_F31 {
-               return 1 << uint(32+r-ppc64.REG_F0)
+       if r >= mips.REG_F0 && r <= mips.REG_F31 {
+               return 1 << uint(32+r-mips.REG_F0)
        }
        return 0
 }
@@ -150,7 +150,7 @@ func BtoR(b uint64) int {
        if b == 0 {
                return 0
        }
-       return gc.Bitno(b) + ppc64.REG_R0
+       return gc.Bitno(b) + mips.REG_R0
 }
 
 func BtoF(b uint64) int {
@@ -158,5 +158,5 @@ func BtoF(b uint64) int {
        if b == 0 {
                return 0
        }
-       return gc.Bitno(b) + ppc64.REG_F0
+       return gc.Bitno(b) + mips.REG_F0
 }
index 7b69c344240e0b1161f291f56ef5f42bb3ecfbca..91c48313b7a205a7ffc839cfe31bdc2648a5d35b 100644 (file)
@@ -8,6 +8,7 @@ import (
        "cmd/compile/internal/amd64"
        "cmd/compile/internal/arm"
        "cmd/compile/internal/arm64"
+       "cmd/compile/internal/mips64"
        "cmd/compile/internal/ppc64"
        "cmd/compile/internal/x86"
        "cmd/internal/obj"
@@ -28,6 +29,8 @@ func main() {
                arm.Main()
        case "arm64":
                arm64.Main()
+       case "mips64", "mips64le":
+               mips64.Main()
        case "ppc64", "ppc64le":
                ppc64.Main()
        }