mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/7g: add ARM64 Go compiler, based on 9g
No peep optimizer yet. Change-Id: Ifa5f993cd6ac5e34783c0df41faf772fbce96ae2 Reviewed-on: https://go-review.googlesource.com/7049 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
3d1ce27ba5
commit
02c1a9d87d
13 changed files with 513 additions and 1748 deletions
|
|
@ -7,7 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"cmd/internal/gc"
|
"cmd/internal/gc"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/ppc64"
|
"cmd/internal/obj/arm64"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -250,11 +250,11 @@ func cgen(n *gc.Node, res *gc.Node) {
|
||||||
gc.OGE,
|
gc.OGE,
|
||||||
gc.OGT,
|
gc.OGT,
|
||||||
gc.ONOT:
|
gc.ONOT:
|
||||||
p1 := gc.Gbranch(ppc64.ABR, nil, 0)
|
p1 := gc.Gbranch(arm64.AB, nil, 0)
|
||||||
|
|
||||||
p2 := gc.Pc
|
p2 := gc.Pc
|
||||||
gmove(gc.Nodbool(true), res)
|
gmove(gc.Nodbool(true), res)
|
||||||
p3 := gc.Gbranch(ppc64.ABR, nil, 0)
|
p3 := gc.Gbranch(arm64.AB, nil, 0)
|
||||||
gc.Patch(p1, gc.Pc)
|
gc.Patch(p1, gc.Pc)
|
||||||
bgen(n, true, 0, p2)
|
bgen(n, true, 0, p2)
|
||||||
gmove(gc.Nodbool(false), res)
|
gmove(gc.Nodbool(false), res)
|
||||||
|
|
@ -280,20 +280,10 @@ func cgen(n *gc.Node, res *gc.Node) {
|
||||||
return
|
return
|
||||||
|
|
||||||
case gc.OMINUS:
|
case gc.OMINUS:
|
||||||
if gc.Isfloat[nl.Type.Etype] {
|
|
||||||
nr = gc.Nodintconst(-1)
|
|
||||||
gc.Convlit(&nr, n.Type)
|
|
||||||
a = optoas(gc.OMUL, nl.Type)
|
|
||||||
goto sbop
|
|
||||||
}
|
|
||||||
|
|
||||||
a := optoas(int(n.Op), nl.Type)
|
|
||||||
// unary
|
|
||||||
var n1 gc.Node
|
var n1 gc.Node
|
||||||
regalloc(&n1, nl.Type, res)
|
regalloc(&n1, nl.Type, nil)
|
||||||
|
|
||||||
cgen(nl, &n1)
|
cgen(nl, &n1)
|
||||||
gins(a, nil, &n1)
|
gins(optoas(gc.OMINUS, nl.Type), &n1, &n1)
|
||||||
gmove(&n1, res)
|
gmove(&n1, res)
|
||||||
regfree(&n1)
|
regfree(&n1)
|
||||||
return
|
return
|
||||||
|
|
@ -379,7 +369,7 @@ func cgen(n *gc.Node, res *gc.Node) {
|
||||||
if gc.Isconst(nl, gc.CTSTR) {
|
if gc.Isconst(nl, gc.CTSTR) {
|
||||||
var n1 gc.Node
|
var n1 gc.Node
|
||||||
regalloc(&n1, gc.Types[gc.Tptr], res)
|
regalloc(&n1, gc.Types[gc.Tptr], res)
|
||||||
p1 := gins(ppc64.AMOVD, nil, &n1)
|
p1 := gins(arm64.AMOVD, nil, &n1)
|
||||||
gc.Datastring(nl.Val.U.Sval, &p1.From)
|
gc.Datastring(nl.Val.U.Sval, &p1.From)
|
||||||
gmove(&n1, res)
|
gmove(&n1, res)
|
||||||
regfree(&n1)
|
regfree(&n1)
|
||||||
|
|
@ -403,7 +393,7 @@ func cgen(n *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
gc.Nodconst(&n2, gc.Types[gc.Tptr], 0)
|
gc.Nodconst(&n2, gc.Types[gc.Tptr], 0)
|
||||||
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n1, &n2)
|
gcmp(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n1, &n2)
|
||||||
p1 := gc.Gbranch(optoas(gc.OEQ, gc.Types[gc.Tptr]), nil, 0)
|
p1 := gc.Gbranch(optoas(gc.OEQ, gc.Types[gc.Tptr]), nil, 0)
|
||||||
|
|
||||||
n2 = n1
|
n2 = n1
|
||||||
|
|
@ -444,7 +434,7 @@ func cgen(n *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
gc.Nodconst(&n2, gc.Types[gc.Tptr], 0)
|
gc.Nodconst(&n2, gc.Types[gc.Tptr], 0)
|
||||||
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n1, &n2)
|
gcmp(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n1, &n2)
|
||||||
p1 := gc.Gbranch(optoas(gc.OEQ, gc.Types[gc.Tptr]), nil, 0)
|
p1 := gc.Gbranch(optoas(gc.OEQ, gc.Types[gc.Tptr]), nil, 0)
|
||||||
|
|
||||||
n2 = n1
|
n2 = n1
|
||||||
|
|
@ -690,7 +680,7 @@ func agenr(n *gc.Node, a *gc.Node, res *gc.Node) {
|
||||||
gc.Cgen_checknil(a)
|
gc.Cgen_checknil(a)
|
||||||
|
|
||||||
case gc.OINDEX:
|
case gc.OINDEX:
|
||||||
var p2 *obj.Prog // to be patched to panicindex.
|
p2 := (*obj.Prog)(nil) // to be patched to panicindex.
|
||||||
w := uint32(n.Type.Width)
|
w := uint32(n.Type.Width)
|
||||||
|
|
||||||
//bounded = debug['B'] || n->bounded;
|
//bounded = debug['B'] || n->bounded;
|
||||||
|
|
@ -796,13 +786,13 @@ func agenr(n *gc.Node, a *gc.Node, res *gc.Node) {
|
||||||
gc.Nodconst(&n4, gc.Types[gc.TUINT64], nl.Type.Bound)
|
gc.Nodconst(&n4, gc.Types[gc.TUINT64], nl.Type.Bound)
|
||||||
} else {
|
} else {
|
||||||
regalloc(&n4, gc.Types[gc.TUINT64], nil)
|
regalloc(&n4, gc.Types[gc.TUINT64], nil)
|
||||||
p1 := gins(ppc64.AMOVD, nil, &n4)
|
p1 := gins(arm64.AMOVD, nil, &n4)
|
||||||
p1.From.Type = obj.TYPE_CONST
|
p1.From.Type = obj.TYPE_CONST
|
||||||
p1.From.Offset = nl.Type.Bound
|
p1.From.Offset = nl.Type.Bound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gins(optoas(gc.OCMP, gc.Types[gc.TUINT64]), &n2, &n4)
|
gcmp(optoas(gc.OCMP, gc.Types[gc.TUINT64]), &n2, &n4)
|
||||||
if n4.Op == gc.OREGISTER {
|
if n4.Op == gc.OREGISTER {
|
||||||
regfree(&n4)
|
regfree(&n4)
|
||||||
}
|
}
|
||||||
|
|
@ -816,7 +806,7 @@ func agenr(n *gc.Node, a *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
if gc.Isconst(nl, gc.CTSTR) {
|
if gc.Isconst(nl, gc.CTSTR) {
|
||||||
regalloc(&n3, gc.Types[gc.Tptr], res)
|
regalloc(&n3, gc.Types[gc.Tptr], res)
|
||||||
p1 := gins(ppc64.AMOVD, nil, &n3)
|
p1 := gins(arm64.AMOVD, nil, &n3)
|
||||||
gc.Datastring(nl.Val.U.Sval, &p1.From)
|
gc.Datastring(nl.Val.U.Sval, &p1.From)
|
||||||
p1.From.Type = obj.TYPE_ADDR
|
p1.From.Type = obj.TYPE_ADDR
|
||||||
} else if gc.Isslice(nl.Type) || nl.Type.Etype == gc.TSTRING {
|
} else if gc.Isslice(nl.Type) || nl.Type.Etype == gc.TSTRING {
|
||||||
|
|
@ -897,7 +887,7 @@ func agen(n *gc.Node, res *gc.Node) {
|
||||||
var n3 gc.Node
|
var n3 gc.Node
|
||||||
n3.Op = gc.OADDR
|
n3.Op = gc.OADDR
|
||||||
n3.Left = &n1
|
n3.Left = &n1
|
||||||
gins(ppc64.AMOVD, &n3, &n2)
|
gins(arm64.AMOVD, &n3, &n2)
|
||||||
gmove(&n2, res)
|
gmove(&n2, res)
|
||||||
regfree(&n2)
|
regfree(&n2)
|
||||||
return
|
return
|
||||||
|
|
@ -909,7 +899,7 @@ func agen(n *gc.Node, res *gc.Node) {
|
||||||
n1.Left = n
|
n1.Left = n
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
regalloc(&n2, gc.Types[gc.Tptr], res)
|
regalloc(&n2, gc.Types[gc.Tptr], res)
|
||||||
gins(ppc64.AMOVD, &n1, &n2)
|
gins(arm64.AMOVD, &n1, &n2)
|
||||||
gmove(&n2, res)
|
gmove(&n2, res)
|
||||||
regfree(&n2)
|
regfree(&n2)
|
||||||
return
|
return
|
||||||
|
|
@ -1020,7 +1010,7 @@ func igen(n *gc.Node, a *gc.Node, res *gc.Node) {
|
||||||
// Increase the refcount of the register so that igen's caller
|
// Increase the refcount of the register so that igen's caller
|
||||||
// has to call regfree.
|
// has to call regfree.
|
||||||
case gc.OINDREG:
|
case gc.OINDREG:
|
||||||
if n.Val.U.Reg != ppc64.REGSP {
|
if n.Val.U.Reg != arm64.REGSP {
|
||||||
reg[n.Val.U.Reg]++
|
reg[n.Val.U.Reg]++
|
||||||
}
|
}
|
||||||
*a = *n
|
*a = *n
|
||||||
|
|
@ -1060,7 +1050,7 @@ func igen(n *gc.Node, a *gc.Node, res *gc.Node) {
|
||||||
fp := gc.Structfirst(&flist, gc.Getoutarg(n.Left.Type))
|
fp := gc.Structfirst(&flist, gc.Getoutarg(n.Left.Type))
|
||||||
*a = gc.Node{}
|
*a = gc.Node{}
|
||||||
a.Op = gc.OINDREG
|
a.Op = gc.OINDREG
|
||||||
a.Val.U.Reg = ppc64.REGSP
|
a.Val.U.Reg = arm64.REGSP
|
||||||
a.Addable = 1
|
a.Addable = 1
|
||||||
a.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved lr at 0(SP)
|
a.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved lr at 0(SP)
|
||||||
a.Type = n.Type
|
a.Type = n.Type
|
||||||
|
|
@ -1149,10 +1139,10 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
cgen(n, &n1)
|
cgen(n, &n1)
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
gc.Nodconst(&n2, n.Type, 0)
|
gc.Nodconst(&n2, n.Type, 0)
|
||||||
gins(optoas(gc.OCMP, n.Type), &n1, &n2)
|
gcmp(optoas(gc.OCMP, n.Type), &n1, &n2)
|
||||||
a := ppc64.ABNE
|
a := arm64.ABNE
|
||||||
if !true_ {
|
if !true_ {
|
||||||
a = ppc64.ABEQ
|
a = arm64.ABEQ
|
||||||
}
|
}
|
||||||
gc.Patch(gc.Gbranch(a, n.Type, likely), to)
|
gc.Patch(gc.Gbranch(a, n.Type, likely), to)
|
||||||
regfree(&n1)
|
regfree(&n1)
|
||||||
|
|
@ -1161,7 +1151,7 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
// need to ask if it is bool?
|
// need to ask if it is bool?
|
||||||
case gc.OLITERAL:
|
case gc.OLITERAL:
|
||||||
if !true_ == (n.Val.U.Bval == 0) {
|
if !true_ == (n.Val.U.Bval == 0) {
|
||||||
gc.Patch(gc.Gbranch(ppc64.ABR, nil, likely), to)
|
gc.Patch(gc.Gbranch(arm64.AB, nil, likely), to)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1218,15 +1208,15 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
if !true_ {
|
if !true_ {
|
||||||
if gc.Isfloat[nr.Type.Etype] {
|
if gc.Isfloat[nr.Type.Etype] {
|
||||||
// brcom is not valid on floats when NaN is involved.
|
// brcom is not valid on floats when NaN is involved.
|
||||||
p1 := gc.Gbranch(ppc64.ABR, nil, 0)
|
p1 := gc.Gbranch(arm64.AB, nil, 0)
|
||||||
|
|
||||||
p2 := gc.Gbranch(ppc64.ABR, nil, 0)
|
p2 := gc.Gbranch(arm64.AB, nil, 0)
|
||||||
gc.Patch(p1, gc.Pc)
|
gc.Patch(p1, gc.Pc)
|
||||||
ll := n.Ninit // avoid re-genning ninit
|
ll := n.Ninit // avoid re-genning ninit
|
||||||
n.Ninit = nil
|
n.Ninit = nil
|
||||||
bgen(n, true, -likely, p2)
|
bgen(n, true, -likely, p2)
|
||||||
n.Ninit = ll
|
n.Ninit = ll
|
||||||
gc.Patch(gc.Gbranch(ppc64.ABR, nil, 0), to)
|
gc.Patch(gc.Gbranch(arm64.AB, nil, 0), to)
|
||||||
gc.Patch(p2, gc.Pc)
|
gc.Patch(p2, gc.Pc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1260,7 +1250,7 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
regalloc(&n2, gc.Types[gc.Tptr], &n1)
|
regalloc(&n2, gc.Types[gc.Tptr], &n1)
|
||||||
gmove(&n1, &n2)
|
gmove(&n1, &n2)
|
||||||
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
|
gcmp(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
|
||||||
regfree(&n2)
|
regfree(&n2)
|
||||||
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
|
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
|
||||||
regfree(&n1)
|
regfree(&n1)
|
||||||
|
|
@ -1283,7 +1273,7 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
var n2 gc.Node
|
var n2 gc.Node
|
||||||
regalloc(&n2, gc.Types[gc.Tptr], &n1)
|
regalloc(&n2, gc.Types[gc.Tptr], &n1)
|
||||||
gmove(&n1, &n2)
|
gmove(&n1, &n2)
|
||||||
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
|
gcmp(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
|
||||||
regfree(&n2)
|
regfree(&n2)
|
||||||
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
|
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
|
||||||
regfree(&n1)
|
regfree(&n1)
|
||||||
|
|
@ -1317,24 +1307,13 @@ func bgen(n *gc.Node, true_ bool, likely int, to *obj.Prog) {
|
||||||
|
|
||||||
regalloc(&n1, nl.Type, nil)
|
regalloc(&n1, nl.Type, nil)
|
||||||
cgen(nl, &n1)
|
cgen(nl, &n1)
|
||||||
|
|
||||||
// TODO(minux): cmpi does accept 16-bit signed immediate as p->to.
|
|
||||||
// and cmpli accepts 16-bit unsigned immediate.
|
|
||||||
//if(smallintconst(nr)) {
|
|
||||||
// gins(optoas(OCMP, nr->type), &n1, nr);
|
|
||||||
// patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
|
|
||||||
// regfree(&n1);
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
regalloc(&n2, nr.Type, nil)
|
regalloc(&n2, nr.Type, nil)
|
||||||
|
|
||||||
cgen(nr, &n2)
|
cgen(nr, &n2)
|
||||||
|
|
||||||
cmp:
|
cmp:
|
||||||
l := &n1
|
l := &n1
|
||||||
r := &n2
|
r := &n2
|
||||||
gins(optoas(gc.OCMP, nr.Type), l, r)
|
gcmp(optoas(gc.OCMP, nr.Type), l, r)
|
||||||
if gc.Isfloat[nr.Type.Etype] && (a == gc.OLE || a == gc.OGE) {
|
if gc.Isfloat[nr.Type.Etype] && (a == gc.OLE || a == gc.OGE) {
|
||||||
// To get NaN right, must rewrite x <= y into separate x < y or x = y.
|
// To get NaN right, must rewrite x <= y into separate x < y or x = y.
|
||||||
switch a {
|
switch a {
|
||||||
|
|
@ -1470,16 +1449,16 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
gc.Fatal("sgen: invalid alignment %d for %v", align, gc.Tconv(n.Type, 0))
|
gc.Fatal("sgen: invalid alignment %d for %v", align, gc.Tconv(n.Type, 0))
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
op = ppc64.AMOVBU
|
op = arm64.AMOVB
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
op = ppc64.AMOVHU
|
op = arm64.AMOVH
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
op = ppc64.AMOVWZU // there is no lwau, only lwaux
|
op = arm64.AMOVW
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
op = ppc64.AMOVDU
|
op = arm64.AMOVD
|
||||||
}
|
}
|
||||||
|
|
||||||
if w%int64(align) != 0 {
|
if w%int64(align) != 0 {
|
||||||
|
|
@ -1521,7 +1500,7 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
if n.Ullman >= res.Ullman {
|
if n.Ullman >= res.Ullman {
|
||||||
agenr(n, &dst, res) // temporarily use dst
|
agenr(n, &dst, res) // temporarily use dst
|
||||||
regalloc(&src, gc.Types[gc.Tptr], nil)
|
regalloc(&src, gc.Types[gc.Tptr], nil)
|
||||||
gins(ppc64.AMOVD, &dst, &src)
|
gins(arm64.AMOVD, &dst, &src)
|
||||||
if res.Op == gc.ONAME {
|
if res.Op == gc.ONAME {
|
||||||
gc.Gvardef(res)
|
gc.Gvardef(res)
|
||||||
}
|
}
|
||||||
|
|
@ -1544,28 +1523,28 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
if dir < 0 {
|
if dir < 0 {
|
||||||
if c >= 4 {
|
if c >= 4 {
|
||||||
regalloc(&nend, gc.Types[gc.Tptr], nil)
|
regalloc(&nend, gc.Types[gc.Tptr], nil)
|
||||||
gins(ppc64.AMOVD, &src, &nend)
|
gins(arm64.AMOVD, &src, &nend)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := gins(ppc64.AADD, nil, &src)
|
p := gins(arm64.AADD, nil, &src)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = w
|
p.From.Offset = w
|
||||||
|
|
||||||
p = gins(ppc64.AADD, nil, &dst)
|
p = gins(arm64.AADD, nil, &dst)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = w
|
p.From.Offset = w
|
||||||
} else {
|
} else {
|
||||||
p := gins(ppc64.AADD, nil, &src)
|
p := gins(arm64.AADD, nil, &src)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = int64(-dir)
|
p.From.Offset = int64(-dir)
|
||||||
|
|
||||||
p = gins(ppc64.AADD, nil, &dst)
|
p = gins(arm64.AADD, nil, &dst)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = int64(-dir)
|
p.From.Offset = int64(-dir)
|
||||||
|
|
||||||
if c >= 4 {
|
if c >= 4 {
|
||||||
regalloc(&nend, gc.Types[gc.Tptr], nil)
|
regalloc(&nend, gc.Types[gc.Tptr], nil)
|
||||||
p := gins(ppc64.AMOVD, &src, &nend)
|
p := gins(arm64.AMOVD, &src, &nend)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
p.From.Offset = w
|
p.From.Offset = w
|
||||||
}
|
}
|
||||||
|
|
@ -1577,15 +1556,17 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
p := gins(op, &src, &tmp)
|
p := gins(op, &src, &tmp)
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Offset = int64(dir)
|
p.From.Offset = int64(dir)
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
ploop := p
|
ploop := p
|
||||||
|
|
||||||
p = gins(op, &tmp, &dst)
|
p = gins(op, &tmp, &dst)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Offset = int64(dir)
|
p.To.Offset = int64(dir)
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
|
|
||||||
p = gins(ppc64.ACMP, &src, &nend)
|
p = gcmp(arm64.ACMP, &src, &nend)
|
||||||
|
|
||||||
gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), ploop)
|
gc.Patch(gc.Gbranch(arm64.ABNE, nil, 0), ploop)
|
||||||
regfree(&nend)
|
regfree(&nend)
|
||||||
} else {
|
} else {
|
||||||
// TODO(austin): Instead of generating ADD $-8,R8; ADD
|
// TODO(austin): Instead of generating ADD $-8,R8; ADD
|
||||||
|
|
@ -1604,10 +1585,12 @@ func sgen(n *gc.Node, ns *gc.Node, w int64) {
|
||||||
p = gins(op, &src, &tmp)
|
p = gins(op, &src, &tmp)
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Offset = int64(dir)
|
p.From.Offset = int64(dir)
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
|
|
||||||
p = gins(op, &tmp, &dst)
|
p = gins(op, &tmp, &dst)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Offset = int64(dir)
|
p.To.Offset = int64(dir)
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,16 @@ package main
|
||||||
import (
|
import (
|
||||||
"cmd/internal/gc"
|
"cmd/internal/gc"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/ppc64"
|
"cmd/internal/obj/arm64"
|
||||||
)
|
)
|
||||||
|
|
||||||
var thechar int = '9'
|
var thechar int = '7'
|
||||||
|
|
||||||
var thestring string = "ppc64"
|
var thestring string = "arm64"
|
||||||
|
|
||||||
var thelinkarch *obj.LinkArch
|
var thelinkarch *obj.LinkArch = &arm64.Linkarm64
|
||||||
|
|
||||||
func linkarchinit() {
|
func linkarchinit() {
|
||||||
thestring = obj.Getgoarch()
|
|
||||||
gc.Thearch.Thestring = thestring
|
|
||||||
if thestring == "ppc64le" {
|
|
||||||
thelinkarch = &ppc64.Linkppc64le
|
|
||||||
} else {
|
|
||||||
thelinkarch = &ppc64.Linkppc64
|
|
||||||
}
|
|
||||||
gc.Thearch.Thelinkarch = thelinkarch
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var MAXWIDTH int64 = 1 << 50
|
var MAXWIDTH int64 = 1 << 50
|
||||||
|
|
@ -43,7 +35,6 @@ func betypeinit() {
|
||||||
gc.Widthptr = 8
|
gc.Widthptr = 8
|
||||||
gc.Widthint = 8
|
gc.Widthint = 8
|
||||||
gc.Widthreg = 8
|
gc.Widthreg = 8
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -51,8 +42,8 @@ func main() {
|
||||||
gc.Thearch.Thestring = thestring
|
gc.Thearch.Thestring = thestring
|
||||||
gc.Thearch.Thelinkarch = thelinkarch
|
gc.Thearch.Thelinkarch = thelinkarch
|
||||||
gc.Thearch.Typedefs = typedefs
|
gc.Thearch.Typedefs = typedefs
|
||||||
gc.Thearch.REGSP = ppc64.REGSP
|
gc.Thearch.REGSP = arm64.REGSP
|
||||||
gc.Thearch.REGCTXT = ppc64.REGCTXT
|
gc.Thearch.REGCTXT = arm64.REGCTXT
|
||||||
gc.Thearch.MAXWIDTH = MAXWIDTH
|
gc.Thearch.MAXWIDTH = MAXWIDTH
|
||||||
gc.Thearch.Anyregalloc = anyregalloc
|
gc.Thearch.Anyregalloc = anyregalloc
|
||||||
gc.Thearch.Betypeinit = betypeinit
|
gc.Thearch.Betypeinit = betypeinit
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "cmd/internal/obj/ppc64"
|
import "cmd/internal/obj/arm64"
|
||||||
import "cmd/internal/gc"
|
import "cmd/internal/gc"
|
||||||
|
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
var reg [ppc64.NREG + ppc64.NFREG]uint8
|
var reg [arm64.NREG + arm64.NFREG]uint8
|
||||||
|
|
||||||
var panicdiv *gc.Node
|
var panicdiv *gc.Node
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"cmd/internal/gc"
|
"cmd/internal/gc"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/ppc64"
|
"cmd/internal/obj/arm64"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -69,27 +69,31 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
|
||||||
}
|
}
|
||||||
if cnt < int64(4*gc.Widthptr) {
|
if cnt < int64(4*gc.Widthptr) {
|
||||||
for i := int64(0); i < cnt; i += int64(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, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGSP, 8+frame+lo+i)
|
||||||
}
|
}
|
||||||
} else if cnt <= int64(128*gc.Widthptr) {
|
} else if 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 = appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0)
|
||||||
p.Reg = ppc64.REGSP
|
p = appendpp(p, arm64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, arm64.REGRT1, 0)
|
||||||
|
p.Reg = arm64.REGRT1
|
||||||
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
|
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
|
||||||
f := gc.Sysfunc("duffzero")
|
f := gc.Sysfunc("duffzero")
|
||||||
p.To = gc.Naddr(f)
|
p.To = gc.Naddr(f)
|
||||||
gc.Afunclit(&p.To, f)
|
gc.Afunclit(&p.To, f)
|
||||||
p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
|
p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
|
||||||
} else {
|
} else {
|
||||||
p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGTMP, 0)
|
p = appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, arm64.REGTMP, 0)
|
||||||
p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT1, 0)
|
p = appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0)
|
||||||
p.Reg = ppc64.REGSP
|
p = appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT1, 0)
|
||||||
p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, ppc64.REGTMP, 0)
|
p.Reg = arm64.REGRT1
|
||||||
p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
|
p = appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, arm64.REGTMP, 0)
|
||||||
p.Reg = ppc64.REGRT1
|
p = appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT2, 0)
|
||||||
p = appendpp(p, ppc64.AMOVDU, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGRT1, int64(gc.Widthptr))
|
p.Reg = arm64.REGRT1
|
||||||
|
p = appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGRT1, int64(gc.Widthptr))
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
p1 := p
|
p1 := p
|
||||||
p = appendpp(p, ppc64.ACMP, obj.TYPE_REG, ppc64.REGRT1, 0, obj.TYPE_REG, ppc64.REGRT2, 0)
|
p = appendpp(p, arm64.ACMP, obj.TYPE_REG, arm64.REGRT1, 0, obj.TYPE_NONE, 0, 0)
|
||||||
p = appendpp(p, ppc64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
|
p.Reg = arm64.REGRT2
|
||||||
|
p = appendpp(p, arm64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
|
||||||
gc.Patch(p, p1)
|
gc.Patch(p, p1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,20 +116,6 @@ func appendpp(p *obj.Prog, as int, ftype int, freg int, foffset int64, ttype int
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* generate: BL reg, f
|
|
||||||
* where both reg and f are registers.
|
|
||||||
* On power, f must be moved to CTR first.
|
|
||||||
*/
|
|
||||||
func ginsBL(reg *gc.Node, f *gc.Node) {
|
|
||||||
p := gins(ppc64.AMOVD, f, nil)
|
|
||||||
p.To.Type = obj.TYPE_REG
|
|
||||||
p.To.Reg = ppc64.REG_CTR
|
|
||||||
p = gins(ppc64.ABL, reg, nil)
|
|
||||||
p.To.Type = obj.TYPE_REG
|
|
||||||
p.To.Reg = ppc64.REG_CTR
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generate:
|
* generate:
|
||||||
* call f
|
* call f
|
||||||
|
|
@ -157,17 +147,16 @@ func ginscall(f *gc.Node, proc int) {
|
||||||
// However, the stack trace code will show the line
|
// However, the stack trace code will show the line
|
||||||
// of the instruction byte before the return PC.
|
// of the instruction byte before the return PC.
|
||||||
// To avoid that being an unrelated instruction,
|
// To avoid that being an unrelated instruction,
|
||||||
// insert a ppc64 NOP that we will have the right line number.
|
// insert a arm64 NOP that we will have the right line number.
|
||||||
// The ppc64 NOP is really or r0, r0, r0; use that description
|
// The arm64 NOP is really or HINT $0; use that description
|
||||||
// because the NOP pseudo-instruction would be removed by
|
// because the NOP pseudo-instruction would be removed by
|
||||||
// the linker.
|
// the linker.
|
||||||
var reg gc.Node
|
var con gc.Node
|
||||||
gc.Nodreg(®, gc.Types[gc.TINT], ppc64.REG_R0)
|
gc.Nodconst(&con, gc.Types[gc.TINT], 0)
|
||||||
|
gins(arm64.AHINT, &con, nil)
|
||||||
gins(ppc64.AOR, ®, ®)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p := gins(ppc64.ABL, nil, f)
|
p := gins(arm64.ABL, nil, f)
|
||||||
gc.Afunclit(&p.To, f)
|
gc.Afunclit(&p.To, f)
|
||||||
if proc == -1 || gc.Noreturn(p) {
|
if proc == -1 || gc.Noreturn(p) {
|
||||||
gins(obj.AUNDEF, nil, nil)
|
gins(obj.AUNDEF, nil, nil)
|
||||||
|
|
@ -176,17 +165,17 @@ func ginscall(f *gc.Node, proc int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var reg gc.Node
|
var reg gc.Node
|
||||||
gc.Nodreg(®, gc.Types[gc.Tptr], ppc64.REGCTXT)
|
gc.Nodreg(®, gc.Types[gc.Tptr], arm64.REGCTXT)
|
||||||
var r1 gc.Node
|
var r1 gc.Node
|
||||||
gc.Nodreg(&r1, gc.Types[gc.Tptr], ppc64.REG_R3)
|
gc.Nodreg(&r1, gc.Types[gc.Tptr], arm64.REGRT1)
|
||||||
gmove(f, ®)
|
gmove(f, ®)
|
||||||
reg.Op = gc.OINDREG
|
reg.Op = gc.OINDREG
|
||||||
gmove(®, &r1)
|
gmove(®, &r1)
|
||||||
reg.Op = gc.OREGISTER
|
r1.Op = gc.OINDREG
|
||||||
ginsBL(®, &r1)
|
gins(arm64.ABL, nil, &r1)
|
||||||
|
|
||||||
case 3: // normal call of c function pointer
|
case 3: // normal call of c function pointer
|
||||||
ginsBL(nil, f)
|
gins(arm64.ABL, nil, f)
|
||||||
|
|
||||||
case 1, // call in new proc (go)
|
case 1, // call in new proc (go)
|
||||||
2: // deferred call (defer)
|
2: // deferred call (defer)
|
||||||
|
|
@ -194,20 +183,20 @@ func ginscall(f *gc.Node, proc int) {
|
||||||
gc.Nodconst(&con, gc.Types[gc.TINT64], int64(gc.Argsize(f.Type)))
|
gc.Nodconst(&con, gc.Types[gc.TINT64], int64(gc.Argsize(f.Type)))
|
||||||
|
|
||||||
var reg gc.Node
|
var reg gc.Node
|
||||||
gc.Nodreg(®, gc.Types[gc.TINT64], ppc64.REG_R3)
|
gc.Nodreg(®, gc.Types[gc.TINT64], arm64.REGRT1)
|
||||||
var reg2 gc.Node
|
var reg2 gc.Node
|
||||||
gc.Nodreg(®2, gc.Types[gc.TINT64], ppc64.REG_R4)
|
gc.Nodreg(®2, gc.Types[gc.TINT64], arm64.REGRT2)
|
||||||
gmove(f, ®)
|
gmove(f, ®)
|
||||||
|
|
||||||
gmove(&con, ®2)
|
gmove(&con, ®2)
|
||||||
p := gins(ppc64.AMOVW, ®2, nil)
|
p := gins(arm64.AMOVW, ®2, nil)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Reg = ppc64.REGSP
|
p.To.Reg = arm64.REGSP
|
||||||
p.To.Offset = 8
|
p.To.Offset = 8
|
||||||
|
|
||||||
p = gins(ppc64.AMOVD, ®, nil)
|
p = gins(arm64.AMOVD, ®, nil)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Reg = ppc64.REGSP
|
p.To.Reg = arm64.REGSP
|
||||||
p.To.Offset = 16
|
p.To.Offset = 16
|
||||||
|
|
||||||
if proc == 1 {
|
if proc == 1 {
|
||||||
|
|
@ -220,11 +209,10 @@ func ginscall(f *gc.Node, proc int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if proc == 2 {
|
if proc == 2 {
|
||||||
gc.Nodreg(®, gc.Types[gc.TINT64], ppc64.REG_R3)
|
gc.Nodreg(®, gc.Types[gc.TINT64], arm64.REG_R0) // R0 should match runtime.return0
|
||||||
p := gins(ppc64.ACMP, ®, nil)
|
p := gins(arm64.ACMP, ®, nil)
|
||||||
p.To.Type = obj.TYPE_REG
|
p.Reg = arm64.REGZERO
|
||||||
p.To.Reg = ppc64.REG_R0
|
p = gc.Gbranch(arm64.ABEQ, nil, +1)
|
||||||
p = gc.Gbranch(ppc64.ABEQ, nil, +1)
|
|
||||||
cgen_ret(nil)
|
cgen_ret(nil)
|
||||||
gc.Patch(p, gc.Pc)
|
gc.Patch(p, gc.Pc)
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +251,7 @@ func cgen_callinter(n *gc.Node, res *gc.Node, proc int) {
|
||||||
igen(i, &nodi, res) // REG = &inter
|
igen(i, &nodi, res) // REG = &inter
|
||||||
|
|
||||||
var nodsp gc.Node
|
var nodsp gc.Node
|
||||||
gc.Nodindreg(&nodsp, gc.Types[gc.Tptr], ppc64.REGSP)
|
gc.Nodindreg(&nodsp, gc.Types[gc.Tptr], arm64.REGSP)
|
||||||
|
|
||||||
nodsp.Xoffset = int64(gc.Widthptr)
|
nodsp.Xoffset = int64(gc.Widthptr)
|
||||||
if proc != 0 {
|
if proc != 0 {
|
||||||
|
|
@ -295,7 +283,7 @@ func cgen_callinter(n *gc.Node, res *gc.Node, proc int) {
|
||||||
proc = 3
|
proc = 3
|
||||||
} else {
|
} else {
|
||||||
// go/defer. generate go func value.
|
// go/defer. generate go func value.
|
||||||
p := gins(ppc64.AMOVD, &nodo, &nodr) // REG = &(32+offset(REG)) -- i.tab->fun[f]
|
p := gins(arm64.AMOVD, &nodo, &nodr) // REG = &(32+offset(REG)) -- i.tab->fun[f]
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,7 +364,7 @@ func cgen_callret(n *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
var nod gc.Node
|
var nod gc.Node
|
||||||
nod.Op = gc.OINDREG
|
nod.Op = gc.OINDREG
|
||||||
nod.Val.U.Reg = ppc64.REGSP
|
nod.Val.U.Reg = arm64.REGSP
|
||||||
nod.Addable = 1
|
nod.Addable = 1
|
||||||
|
|
||||||
nod.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved LR at 0(R1)
|
nod.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved LR at 0(R1)
|
||||||
|
|
@ -403,7 +391,7 @@ func cgen_aret(n *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
var nod1 gc.Node
|
var nod1 gc.Node
|
||||||
nod1.Op = gc.OINDREG
|
nod1.Op = gc.OINDREG
|
||||||
nod1.Val.U.Reg = ppc64.REGSP
|
nod1.Val.U.Reg = arm64.REGSP
|
||||||
nod1.Addable = 1
|
nod1.Addable = 1
|
||||||
|
|
||||||
nod1.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved lr at 0(SP)
|
nod1.Xoffset = fp.Width + int64(gc.Widthptr) // +widthptr: saved lr at 0(SP)
|
||||||
|
|
@ -413,7 +401,7 @@ func cgen_aret(n *gc.Node, res *gc.Node) {
|
||||||
var nod2 gc.Node
|
var nod2 gc.Node
|
||||||
regalloc(&nod2, gc.Types[gc.Tptr], res)
|
regalloc(&nod2, gc.Types[gc.Tptr], res)
|
||||||
agen(&nod1, &nod2)
|
agen(&nod1, &nod2)
|
||||||
gins(ppc64.AMOVD, &nod2, res)
|
gins(arm64.AMOVD, &nod2, res)
|
||||||
regfree(&nod2)
|
regfree(&nod2)
|
||||||
} else {
|
} else {
|
||||||
agen(&nod1, res)
|
agen(&nod1, res)
|
||||||
|
|
@ -504,9 +492,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
|
||||||
|
|
||||||
// Handle divide-by-zero panic.
|
// Handle divide-by-zero panic.
|
||||||
p1 := gins(optoas(gc.OCMP, t), &tr, nil)
|
p1 := gins(optoas(gc.OCMP, t), &tr, nil)
|
||||||
|
p1.Reg = arm64.REGZERO
|
||||||
p1.To.Type = obj.TYPE_REG
|
|
||||||
p1.To.Reg = ppc64.REGZERO
|
|
||||||
p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
|
p1 = gc.Gbranch(optoas(gc.ONE, t), nil, +1)
|
||||||
if panicdiv == nil {
|
if panicdiv == nil {
|
||||||
panicdiv = gc.Sysfunc("panicdivide")
|
panicdiv = gc.Sysfunc("panicdivide")
|
||||||
|
|
@ -518,11 +504,11 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
|
||||||
if check != 0 {
|
if check != 0 {
|
||||||
var nm1 gc.Node
|
var nm1 gc.Node
|
||||||
gc.Nodconst(&nm1, t, -1)
|
gc.Nodconst(&nm1, t, -1)
|
||||||
gins(optoas(gc.OCMP, t), &tr, &nm1)
|
gcmp(optoas(gc.OCMP, t), &tr, &nm1)
|
||||||
p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
|
p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
|
||||||
if op == gc.ODIV {
|
if op == gc.ODIV {
|
||||||
// a / (-1) is -a.
|
// a / (-1) is -a.
|
||||||
gins(optoas(gc.OMINUS, t), nil, &tl)
|
gins(optoas(gc.OMINUS, t), &tl, &tl)
|
||||||
|
|
||||||
gmove(&tl, res)
|
gmove(&tl, res)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -601,7 +587,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
|
||||||
gc.TINT16,
|
gc.TINT16,
|
||||||
gc.TINT32:
|
gc.TINT32:
|
||||||
gins(optoas(gc.OMUL, t), &n2, &n1)
|
gins(optoas(gc.OMUL, t), &n2, &n1)
|
||||||
p := (*obj.Prog)(gins(ppc64.ASRAD, nil, &n1))
|
p := (*obj.Prog)(gins(arm64.AASR, nil, &n1))
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = int64(w)
|
p.From.Offset = int64(w)
|
||||||
|
|
||||||
|
|
@ -609,16 +595,16 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
|
||||||
gc.TUINT16,
|
gc.TUINT16,
|
||||||
gc.TUINT32:
|
gc.TUINT32:
|
||||||
gins(optoas(gc.OMUL, t), &n2, &n1)
|
gins(optoas(gc.OMUL, t), &n2, &n1)
|
||||||
p := (*obj.Prog)(gins(ppc64.ASRD, nil, &n1))
|
p := (*obj.Prog)(gins(arm64.ALSR, nil, &n1))
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = int64(w)
|
p.From.Offset = int64(w)
|
||||||
|
|
||||||
case gc.TINT64,
|
case gc.TINT64,
|
||||||
gc.TUINT64:
|
gc.TUINT64:
|
||||||
if gc.Issigned[t.Etype] {
|
if gc.Issigned[t.Etype] {
|
||||||
gins(ppc64.AMULHD, &n2, &n1)
|
gins(arm64.ASMULH, &n2, &n1)
|
||||||
} else {
|
} else {
|
||||||
gins(ppc64.AMULHDU, &n2, &n1)
|
gins(arm64.AUMULH, &n2, &n1)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -704,7 +690,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
|
||||||
// test and fix up large shifts
|
// test and fix up large shifts
|
||||||
if !bounded {
|
if !bounded {
|
||||||
gc.Nodconst(&n3, tcount, nl.Type.Width*8)
|
gc.Nodconst(&n3, tcount, nl.Type.Width*8)
|
||||||
gins(optoas(gc.OCMP, tcount), &n1, &n3)
|
gcmp(optoas(gc.OCMP, tcount), &n1, &n3)
|
||||||
p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, tcount), nil, +1))
|
p1 := (*obj.Prog)(gc.Gbranch(optoas(gc.OLT, tcount), nil, +1))
|
||||||
if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
|
if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
|
||||||
gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
|
gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
|
||||||
|
|
@ -740,58 +726,59 @@ func clearfat(nl *gc.Node) {
|
||||||
c := uint64(w % 8) // bytes
|
c := uint64(w % 8) // bytes
|
||||||
q := uint64(w / 8) // dwords
|
q := uint64(w / 8) // dwords
|
||||||
|
|
||||||
if reg[ppc64.REGRT1-ppc64.REG_R0] > 0 {
|
if reg[arm64.REGRT1-arm64.REG_R0] > 0 {
|
||||||
gc.Fatal("R%d in use during clearfat", ppc64.REGRT1-ppc64.REG_R0)
|
gc.Fatal("R%d in use during clearfat", arm64.REGRT1-arm64.REG_R0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 gc.Node
|
var r0 gc.Node
|
||||||
gc.Nodreg(&r0, gc.Types[gc.TUINT64], ppc64.REG_R0) // r0 is always zero
|
gc.Nodreg(&r0, gc.Types[gc.TUINT64], arm64.REGZERO)
|
||||||
var dst gc.Node
|
var dst gc.Node
|
||||||
gc.Nodreg(&dst, gc.Types[gc.Tptr], ppc64.REGRT1)
|
gc.Nodreg(&dst, gc.Types[gc.Tptr], arm64.REGRT1)
|
||||||
reg[ppc64.REGRT1-ppc64.REG_R0]++
|
reg[arm64.REGRT1-arm64.REG_R0]++
|
||||||
agen(nl, &dst)
|
agen(nl, &dst)
|
||||||
|
|
||||||
var boff uint64
|
var boff uint64
|
||||||
if q > 128 {
|
if q > 128 {
|
||||||
p := gins(ppc64.ASUB, nil, &dst)
|
p := gins(arm64.ASUB, nil, &dst)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = 8
|
p.From.Offset = 8
|
||||||
|
|
||||||
var end gc.Node
|
var end gc.Node
|
||||||
regalloc(&end, gc.Types[gc.Tptr], nil)
|
regalloc(&end, gc.Types[gc.Tptr], nil)
|
||||||
p = gins(ppc64.AMOVD, &dst, &end)
|
p = gins(arm64.AMOVD, &dst, &end)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
p.From.Offset = int64(q * 8)
|
p.From.Offset = int64(q * 8)
|
||||||
|
|
||||||
p = gins(ppc64.AMOVDU, &r0, &dst)
|
p = gins(arm64.AMOVD, &r0, &dst)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Offset = 8
|
p.To.Offset = 8
|
||||||
|
p.Scond = arm64.C_XPRE
|
||||||
pl := (*obj.Prog)(p)
|
pl := (*obj.Prog)(p)
|
||||||
|
|
||||||
p = gins(ppc64.ACMP, &dst, &end)
|
p = gcmp(arm64.ACMP, &dst, &end)
|
||||||
gc.Patch(gc.Gbranch(ppc64.ABNE, nil, 0), pl)
|
gc.Patch(gc.Gbranch(arm64.ABNE, nil, 0), pl)
|
||||||
|
|
||||||
regfree(&end)
|
regfree(&end)
|
||||||
|
|
||||||
// The loop leaves R3 on the last zeroed dword
|
// The loop leaves R16 on the last zeroed dword
|
||||||
boff = 8
|
boff = 8
|
||||||
} else if q >= 4 {
|
} else if q >= 4 {
|
||||||
p := gins(ppc64.ASUB, nil, &dst)
|
p := gins(arm64.ASUB, nil, &dst)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = 8
|
p.From.Offset = 8
|
||||||
f := (*gc.Node)(gc.Sysfunc("duffzero"))
|
f := (*gc.Node)(gc.Sysfunc("duffzero"))
|
||||||
p = gins(obj.ADUFFZERO, nil, f)
|
p = gins(obj.ADUFFZERO, nil, f)
|
||||||
gc.Afunclit(&p.To, f)
|
gc.Afunclit(&p.To, f)
|
||||||
|
|
||||||
// 4 and 128 = magic constants: see ../../runtime/asm_ppc64x.s
|
// 4 and 128 = magic constants: see ../../runtime/asm_arm64x.s
|
||||||
p.To.Offset = int64(4 * (128 - q))
|
p.To.Offset = int64(4 * (128 - q))
|
||||||
|
|
||||||
// duffzero leaves R3 on the last zeroed dword
|
// duffzero leaves R16 on the last zeroed dword
|
||||||
boff = 8
|
boff = 8
|
||||||
} else {
|
} else {
|
||||||
var p *obj.Prog
|
var p *obj.Prog
|
||||||
for t := uint64(0); t < q; t++ {
|
for t := uint64(0); t < q; t++ {
|
||||||
p = gins(ppc64.AMOVD, &r0, &dst)
|
p = gins(arm64.AMOVD, &r0, &dst)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Offset = int64(8 * t)
|
p.To.Offset = int64(8 * t)
|
||||||
}
|
}
|
||||||
|
|
@ -801,12 +788,12 @@ func clearfat(nl *gc.Node) {
|
||||||
|
|
||||||
var p *obj.Prog
|
var p *obj.Prog
|
||||||
for t := uint64(0); t < c; t++ {
|
for t := uint64(0); t < c; t++ {
|
||||||
p = gins(ppc64.AMOVB, &r0, &dst)
|
p = gins(arm64.AMOVB, &r0, &dst)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Offset = int64(t + boff)
|
p.To.Offset = int64(t + boff)
|
||||||
}
|
}
|
||||||
|
|
||||||
reg[ppc64.REGRT1-ppc64.REG_R0]--
|
reg[arm64.REGRT1-arm64.REG_R0]--
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after regopt and peep have run.
|
// Called after regopt and peep have run.
|
||||||
|
|
@ -829,26 +816,10 @@ func expandchecks(firstp *obj.Prog) {
|
||||||
gc.Fatal("invalid nil check %v\n", p)
|
gc.Fatal("invalid nil check %v\n", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// check is
|
// check is
|
||||||
// TD $4, R0, arg (R0 is always zero)
|
// CMP arg, ZR
|
||||||
// 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 = REG_R0;
|
|
||||||
p->to.type = TYPE_REG;
|
|
||||||
p->to.reg = reg;
|
|
||||||
*/
|
|
||||||
// check is
|
|
||||||
// CMP arg, R0
|
|
||||||
// BNE 2(PC) [likely]
|
// BNE 2(PC) [likely]
|
||||||
// MOVD R0, 0(R0)
|
// MOVD ZR, 0(arg)
|
||||||
p1 = gc.Ctxt.NewProg()
|
p1 = gc.Ctxt.NewProg()
|
||||||
|
|
||||||
p2 = gc.Ctxt.NewProg()
|
p2 = gc.Ctxt.NewProg()
|
||||||
|
|
@ -861,10 +832,9 @@ func expandchecks(firstp *obj.Prog) {
|
||||||
p2.Lineno = p.Lineno
|
p2.Lineno = p.Lineno
|
||||||
p1.Pc = 9999
|
p1.Pc = 9999
|
||||||
p2.Pc = 9999
|
p2.Pc = 9999
|
||||||
p.As = ppc64.ACMP
|
p.As = arm64.ACMP
|
||||||
p.To.Type = obj.TYPE_REG
|
p.Reg = arm64.REGZERO
|
||||||
p.To.Reg = ppc64.REGZERO
|
p1.As = arm64.ABNE
|
||||||
p1.As = ppc64.ABNE
|
|
||||||
|
|
||||||
//p1->from.type = TYPE_CONST;
|
//p1->from.type = TYPE_CONST;
|
||||||
//p1->from.offset = 1; // likely
|
//p1->from.offset = 1; // likely
|
||||||
|
|
@ -873,12 +843,11 @@ func expandchecks(firstp *obj.Prog) {
|
||||||
p1.To.U.Branch = p2.Link
|
p1.To.U.Branch = p2.Link
|
||||||
|
|
||||||
// crash by write to memory address 0.
|
// crash by write to memory address 0.
|
||||||
p2.As = ppc64.AMOVD
|
p2.As = arm64.AMOVD
|
||||||
|
|
||||||
p2.From.Type = obj.TYPE_REG
|
p2.From.Type = obj.TYPE_REG
|
||||||
p2.From.Reg = ppc64.REG_R0
|
p2.From.Reg = arm64.REGZERO
|
||||||
p2.To.Type = obj.TYPE_MEM
|
p2.To.Type = obj.TYPE_MEM
|
||||||
p2.To.Reg = ppc64.REG_R0
|
p2.To.Reg = p.From.Reg
|
||||||
p2.To.Offset = 0
|
p2.To.Offset = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -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 main
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,7 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"cmd/internal/gc"
|
"cmd/internal/gc"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/ppc64"
|
"cmd/internal/obj/arm64"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -24,7 +24,7 @@ const (
|
||||||
// size variants of an operation even if we just use a subset.
|
// size variants of an operation even if we just use a subset.
|
||||||
//
|
//
|
||||||
// The table is formatted for 8-space tabs.
|
// The table is formatted for 8-space tabs.
|
||||||
var progtable = [ppc64.ALAST]gc.ProgInfo{
|
var progtable = [arm64.ALAST]gc.ProgInfo{
|
||||||
obj.ATYPE: gc.ProgInfo{gc.Pseudo | gc.Skip, 0, 0, 0},
|
obj.ATYPE: gc.ProgInfo{gc.Pseudo | gc.Skip, 0, 0, 0},
|
||||||
obj.ATEXT: gc.ProgInfo{gc.Pseudo, 0, 0, 0},
|
obj.ATEXT: gc.ProgInfo{gc.Pseudo, 0, 0, 0},
|
||||||
obj.AFUNCDATA: gc.ProgInfo{gc.Pseudo, 0, 0, 0},
|
obj.AFUNCDATA: gc.ProgInfo{gc.Pseudo, 0, 0, 0},
|
||||||
|
|
@ -38,107 +38,98 @@ var progtable = [ppc64.ALAST]gc.ProgInfo{
|
||||||
// NOP is an internal no-op that also stands
|
// 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 Power opcode.
|
||||||
obj.ANOP: gc.ProgInfo{gc.LeftRead | gc.RightWrite, 0, 0, 0},
|
obj.ANOP: gc.ProgInfo{gc.LeftRead | gc.RightWrite, 0, 0, 0},
|
||||||
|
arm64.AHINT: gc.ProgInfo{gc.OK, 0, 0, 0},
|
||||||
|
|
||||||
// Integer
|
// Integer
|
||||||
ppc64.AADD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AADD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ASUB: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ASUB: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ANEG: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ANEG: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AAND: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AAND: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AOR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AORR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AXOR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AEOR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AMULLD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AMUL: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AMULLW: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ASMULL: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AMULHD: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AUMULL: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AMULHDU: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ASMULH: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ADIVD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AUMULH: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ADIVDU: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ASDIV: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ASLD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AUDIV: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ASRD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ALSL: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ASRAD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.ALSR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ACMP: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
arm64.AASR: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.ACMPU: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
arm64.ACMP: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
||||||
ppc64.ATD: gc.ProgInfo{gc.SizeQ | gc.RightRead, 0, 0, 0},
|
|
||||||
|
|
||||||
// Floating point.
|
// Floating point.
|
||||||
ppc64.AFADD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFADDD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFADDS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFADDS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFSUB: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFSUBD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFSUBS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFSUBS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFMUL: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFNEGD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFMULS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFNEGS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFDIV: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFMULD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFDIVS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFMULS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFCTIDZ: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFDIVD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFCFID: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
arm64.AFDIVS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
|
||||||
ppc64.AFCMPU: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
arm64.AFCMPD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
||||||
ppc64.AFRSP: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
arm64.AFCMPS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightRead, 0, 0, 0},
|
||||||
|
|
||||||
|
// float -> integer
|
||||||
|
arm64.AFCVTZSD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZSS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZSDW: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZSSW: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZUD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZUS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZUDW: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTZUSW: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
|
||||||
|
// float -> float
|
||||||
|
arm64.AFCVTSD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AFCVTDS: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
|
||||||
|
// integer -> float
|
||||||
|
arm64.ASCVTFD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.ASCVTFS: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.ASCVTFWD: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.ASCVTFWS: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AUCVTFD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AUCVTFS: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AUCVTFWD: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
arm64.AUCVTFWS: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
|
||||||
|
|
||||||
// Moves
|
// Moves
|
||||||
ppc64.AMOVB: gc.ProgInfo{gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
arm64.AMOVB: gc.ProgInfo{gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVBU: gc.ProgInfo{gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
|
arm64.AMOVBU: gc.ProgInfo{gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVBZ: gc.ProgInfo{gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
arm64.AMOVH: gc.ProgInfo{gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVH: gc.ProgInfo{gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
arm64.AMOVHU: gc.ProgInfo{gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVHU: gc.ProgInfo{gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
|
arm64.AMOVW: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVHZ: gc.ProgInfo{gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
arm64.AMOVWU: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
ppc64.AMOVW: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
arm64.AMOVD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
|
||||||
|
arm64.AFMOVS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
||||||
// there is no AMOVWU.
|
arm64.AFMOVD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
|
||||||
ppc64.AMOVWZU: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
|
|
||||||
ppc64.AMOVWZ: gc.ProgInfo{gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
|
||||||
ppc64.AMOVD: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
|
|
||||||
ppc64.AMOVDU: gc.ProgInfo{gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc, 0, 0, 0},
|
|
||||||
ppc64.AFMOVS: gc.ProgInfo{gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
|
|
||||||
ppc64.AFMOVD: gc.ProgInfo{gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
|
|
||||||
|
|
||||||
// Jumps
|
// Jumps
|
||||||
ppc64.ABR: gc.ProgInfo{gc.Jump | gc.Break, 0, 0, 0},
|
arm64.AB: gc.ProgInfo{gc.Jump | gc.Break, 0, 0, 0},
|
||||||
ppc64.ABL: gc.ProgInfo{gc.Call, 0, 0, 0},
|
arm64.ABL: gc.ProgInfo{gc.Call, 0, 0, 0},
|
||||||
ppc64.ABEQ: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABEQ: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ABNE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABNE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ABGE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABGE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ABLT: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABLT: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ABGT: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABGT: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ABLE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
arm64.ABLE: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
ppc64.ARETURN: gc.ProgInfo{gc.Break, 0, 0, 0},
|
arm64.ABLO: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
|
arm64.ABLS: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
|
arm64.ABHI: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
|
arm64.ABHS: gc.ProgInfo{gc.Cjmp, 0, 0, 0},
|
||||||
|
obj.ARET: gc.ProgInfo{gc.Break, 0, 0, 0},
|
||||||
obj.ADUFFZERO: gc.ProgInfo{gc.Call, 0, 0, 0},
|
obj.ADUFFZERO: gc.ProgInfo{gc.Call, 0, 0, 0},
|
||||||
obj.ADUFFCOPY: gc.ProgInfo{gc.Call, 0, 0, 0},
|
obj.ADUFFCOPY: gc.ProgInfo{gc.Call, 0, 0, 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
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) (info gc.ProgInfo) {
|
func proginfo(p *obj.Prog) (info gc.ProgInfo) {
|
||||||
initproginfo()
|
|
||||||
|
|
||||||
info = progtable[p.As]
|
info = progtable[p.As]
|
||||||
if info.Flags == 0 {
|
if info.Flags == 0 {
|
||||||
info = progtable[ppc64.AADD]
|
info = progtable[arm64.AADD]
|
||||||
gc.Fatal("proginfo: unknown instruction %v", p)
|
gc.Fatal("proginfo: unknown instruction %v", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,14 +140,14 @@ func proginfo(p *obj.Prog) (info gc.ProgInfo) {
|
||||||
|
|
||||||
if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
|
if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
|
||||||
info.Regindex |= RtoB(int(p.From.Reg))
|
info.Regindex |= RtoB(int(p.From.Reg))
|
||||||
if info.Flags&gc.PostInc != 0 {
|
if p.Scond != 0 {
|
||||||
info.Regset |= RtoB(int(p.From.Reg))
|
info.Regset |= RtoB(int(p.From.Reg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
|
if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
|
||||||
info.Regindex |= RtoB(int(p.To.Reg))
|
info.Regindex |= RtoB(int(p.To.Reg))
|
||||||
if info.Flags&gc.PostInc != 0 {
|
if p.Scond != 0 {
|
||||||
info.Regset |= RtoB(int(p.To.Reg))
|
info.Regset |= RtoB(int(p.To.Reg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,150 +158,16 @@ func proginfo(p *obj.Prog) (info gc.ProgInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.As == obj.ADUFFZERO {
|
if p.As == obj.ADUFFZERO {
|
||||||
info.Reguse |= 1<<0 | RtoB(ppc64.REG_R3)
|
info.Reguse |= RtoB(arm64.REGRT1)
|
||||||
info.Regset |= RtoB(ppc64.REG_R3)
|
info.Regset |= RtoB(arm64.REGRT1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.As == obj.ADUFFCOPY {
|
if p.As == obj.ADUFFCOPY {
|
||||||
// TODO(austin) Revisit when duffcopy is implemented
|
// TODO(austin) Revisit when duffcopy is implemented
|
||||||
info.Reguse |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4) | RtoB(ppc64.REG_R5)
|
info.Reguse |= RtoB(arm64.REGRT1) | RtoB(arm64.REGRT2) | RtoB(arm64.REG_R5)
|
||||||
|
|
||||||
info.Regset |= RtoB(ppc64.REG_R3) | RtoB(ppc64.REG_R4)
|
info.Regset |= RtoB(arm64.REGRT1) | RtoB(arm64.REGRT2)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gc.Fatal("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]
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,10 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "cmd/internal/obj/ppc64"
|
import (
|
||||||
import "cmd/internal/gc"
|
"cmd/internal/gc"
|
||||||
|
"cmd/internal/obj/arm64"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NREGVAR = 64 /* 32 general + 32 floating */
|
NREGVAR = 64 /* 32 general + 32 floating */
|
||||||
|
|
@ -111,10 +113,10 @@ func regnames(n *int) []string {
|
||||||
|
|
||||||
func excludedregs() uint64 {
|
func excludedregs() uint64 {
|
||||||
// Exclude registers with fixed functions
|
// Exclude registers with fixed functions
|
||||||
regbits := uint64(1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS))
|
regbits := uint64(RtoB(arm64.REGRT1) | RtoB(arm64.REGRT2) | RtoB(arm64.REGPR))
|
||||||
|
|
||||||
// Also exclude floating point registers with fixed constants
|
// 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(arm64.REG_F27) | RtoB(arm64.REG_F28) | RtoB(arm64.REG_F29) | RtoB(arm64.REG_F30) | RtoB(arm64.REG_F31)
|
||||||
|
|
||||||
return regbits
|
return regbits
|
||||||
}
|
}
|
||||||
|
|
@ -136,11 +138,11 @@ func doregbits(r int) uint64 {
|
||||||
* 32+31 F31
|
* 32+31 F31
|
||||||
*/
|
*/
|
||||||
func RtoB(r int) uint64 {
|
func RtoB(r int) uint64 {
|
||||||
if r > ppc64.REG_R0 && r <= ppc64.REG_R31 {
|
if r >= arm64.REG_R0 && r <= arm64.REG_R31 {
|
||||||
return 1 << uint(r-ppc64.REG_R0)
|
return 1 << uint(r-arm64.REG_R0)
|
||||||
}
|
}
|
||||||
if r >= ppc64.REG_F0 && r <= ppc64.REG_F31 {
|
if r >= arm64.REG_F0 && r <= arm64.REG_F31 {
|
||||||
return 1 << uint(32+r-ppc64.REG_F0)
|
return 1 << uint(32+r-arm64.REG_F0)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +152,7 @@ func BtoR(b uint64) int {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return gc.Bitno(b) + ppc64.REG_R0
|
return gc.Bitno(b) + arm64.REG_R0
|
||||||
}
|
}
|
||||||
|
|
||||||
func BtoF(b uint64) int {
|
func BtoF(b uint64) int {
|
||||||
|
|
@ -158,5 +160,5 @@ func BtoF(b uint64) int {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return gc.Bitno(b) + ppc64.REG_F0
|
return gc.Bitno(b) + arm64.REG_F0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ func Gbranch(as int, t *Type, likely int) *obj.Prog {
|
||||||
p := Prog(as)
|
p := Prog(as)
|
||||||
p.To.Type = obj.TYPE_BRANCH
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
p.To.U.Branch = nil
|
p.To.U.Branch = nil
|
||||||
if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' {
|
if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' {
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = int64(bool2int(likely > 0))
|
p.From.Offset = int64(bool2int(likely > 0))
|
||||||
}
|
}
|
||||||
|
|
@ -423,7 +423,7 @@ func Naddr(n *Node) (a obj.Addr) {
|
||||||
case OADDR:
|
case OADDR:
|
||||||
a = Naddr(n.Left)
|
a = Naddr(n.Left)
|
||||||
a.Etype = uint8(Tptr)
|
a.Etype = uint8(Tptr)
|
||||||
if Thearch.Thechar != '5' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
|
if Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
|
||||||
a.Width = int64(Widthptr)
|
a.Width = int64(Widthptr)
|
||||||
}
|
}
|
||||||
if a.Type != obj.TYPE_MEM {
|
if a.Type != obj.TYPE_MEM {
|
||||||
|
|
@ -461,7 +461,7 @@ func Naddr(n *Node) (a obj.Addr) {
|
||||||
break // len(nil)
|
break // len(nil)
|
||||||
}
|
}
|
||||||
a.Etype = Simtype[TUINT]
|
a.Etype = Simtype[TUINT]
|
||||||
if Thearch.Thechar == '9' {
|
if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
a.Etype = Simtype[TINT]
|
a.Etype = Simtype[TINT]
|
||||||
}
|
}
|
||||||
a.Offset += int64(Array_nel)
|
a.Offset += int64(Array_nel)
|
||||||
|
|
@ -477,7 +477,7 @@ func Naddr(n *Node) (a obj.Addr) {
|
||||||
break // cap(nil)
|
break // cap(nil)
|
||||||
}
|
}
|
||||||
a.Etype = Simtype[TUINT]
|
a.Etype = Simtype[TUINT]
|
||||||
if Thearch.Thechar == '9' {
|
if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
a.Etype = Simtype[TINT]
|
a.Etype = Simtype[TINT]
|
||||||
}
|
}
|
||||||
a.Offset += int64(Array_cap)
|
a.Offset += int64(Array_cap)
|
||||||
|
|
@ -560,7 +560,7 @@ fp:
|
||||||
if Thearch.Thechar == '5' {
|
if Thearch.Thechar == '5' {
|
||||||
n.Xoffset += 4
|
n.Xoffset += 4
|
||||||
}
|
}
|
||||||
if Thearch.Thechar == '9' {
|
if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
n.Xoffset += 8
|
n.Xoffset += 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ func allocauto(ptxt *obj.Prog) {
|
||||||
if haspointers(n.Type) {
|
if haspointers(n.Type) {
|
||||||
stkptrsize = Stksize
|
stkptrsize = Stksize
|
||||||
}
|
}
|
||||||
if Thearch.Thechar == '5' || Thearch.Thechar == '9' {
|
if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
Stksize = Rnd(Stksize, int64(Widthptr))
|
Stksize = Rnd(Stksize, int64(Widthptr))
|
||||||
}
|
}
|
||||||
if Stksize >= 1<<31 {
|
if Stksize >= 1<<31 {
|
||||||
|
|
@ -333,7 +333,7 @@ func Cgen_checknil(n *Node) {
|
||||||
Fatal("bad checknil")
|
Fatal("bad checknil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Thearch.Thechar == '5' || Thearch.Thechar == '9') && n.Op != OREGISTER) || n.Addable == 0 || n.Op == OLITERAL {
|
if ((Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || n.Addable == 0 || n.Op == OLITERAL {
|
||||||
var reg Node
|
var reg Node
|
||||||
Thearch.Regalloc(®, Types[Tptr], n)
|
Thearch.Regalloc(®, Types[Tptr], n)
|
||||||
Thearch.Cgen(n, ®)
|
Thearch.Cgen(n, ®)
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ func addmove(r *Flow, bn int, rn int, f int) {
|
||||||
p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)]))
|
p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)]))
|
||||||
|
|
||||||
// TODO(rsc): Remove special case here.
|
// TODO(rsc): Remove special case here.
|
||||||
if (Thearch.Thechar == '9' || Thearch.Thechar == '5') && v.etype == TBOOL {
|
if (Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
|
||||||
p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8]))
|
p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8]))
|
||||||
}
|
}
|
||||||
p1.From.Type = obj.TYPE_REG
|
p1.From.Type = obj.TYPE_REG
|
||||||
|
|
@ -209,7 +209,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
|
||||||
// TODO(rsc): Remove special case here.
|
// TODO(rsc): Remove special case here.
|
||||||
case obj.TYPE_ADDR:
|
case obj.TYPE_ADDR:
|
||||||
var bit Bits
|
var bit Bits
|
||||||
if Thearch.Thechar == '9' || Thearch.Thechar == '5' {
|
if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
goto memcase
|
goto memcase
|
||||||
}
|
}
|
||||||
a.Type = obj.TYPE_MEM
|
a.Type = obj.TYPE_MEM
|
||||||
|
|
|
||||||
|
|
@ -3625,7 +3625,7 @@ func samecheap(a *Node, b *Node) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkrotate(np **Node) {
|
func walkrotate(np **Node) {
|
||||||
if Thearch.Thechar == '9' {
|
if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3757,7 +3757,7 @@ func walkdiv(np **Node, init **NodeList) {
|
||||||
// if >= 0, nr is 1<<pow // 1 if nr is negative.
|
// if >= 0, nr is 1<<pow // 1 if nr is negative.
|
||||||
|
|
||||||
// TODO(minux)
|
// TODO(minux)
|
||||||
if Thearch.Thechar == '9' {
|
if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue