作者:tidatid
项目:g
/*
* generate an addressable node in res, containing the value of n.
* n is an array index, and might be any size; res width is <= 32-bit.
* returns Prog* to patch to panic call.
*/
func igenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
if !gc.Is64(n.Type) {
if n.Addable != 0 {
// nothing to do.
*res = *n
} else {
gc.Tempname(res, gc.Types[gc.TUINT32])
gc.Cgen(n, res)
}
return nil
}
var tmp gc.Node
gc.Tempname(&tmp, gc.Types[gc.TINT64])
gc.Cgen(n, &tmp)
var lo gc.Node
var hi gc.Node
split64(&tmp, &lo, &hi)
gc.Tempname(res, gc.Types[gc.TUINT32])
gmove(&lo, res)
if bounded {
splitclean()
return nil
}
var zero gc.Node
gc.Nodconst(&zero, gc.Types[gc.TINT32], 0)
gins(x86.ACMPL, &hi, &zero)
splitclean()
return gc.Gbranch(x86.AJNE, nil, +1)
}
作者:bibbyflyawa
项目:g
/*
* generate array index into res.
* n might be any size; res is 32-bit.
* returns Prog* to patch to panic call.
*/
func cgenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
if !gc.Is64(n.Type) {
gc.Cgen(n, res)
return nil
}
var tmp gc.Node
gc.Tempname(&tmp, gc.Types[gc.TINT64])
gc.Cgen(n, &tmp)
var lo gc.Node
var hi gc.Node
split64(&tmp, &lo, &hi)
gmove(&lo, res)
if bounded {
splitclean()
return nil
}
var n1 gc.Node
gc.Regalloc(&n1, gc.Types[gc.TINT32], nil)
var n2 gc.Node
gc.Regalloc(&n2, gc.Types[gc.TINT32], nil)
var zero gc.Node
gc.Nodconst(&zero, gc.Types[gc.TINT32], 0)
gmove(&hi, &n1)
gmove(&zero, &n2)
gins(arm.ACMP, &n1, &n2)
gc.Regfree(&n2)
gc.Regfree(&n1)
splitclean()
return gc.Gbranch(arm.ABNE, nil, -1)
}
作者:kluesk
项目:go-akaro
/*
* generate byte multiply:
* res = nl * nr
* there is no 2-operand byte multiply instruction so
* we do a full-width multiplication and truncate afterwards.
*/
func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
// copy from byte to full registers
t := gc.Types[gc.TUINT32]
if gc.Issigned[nl.Type.Etype] {
t = gc.Types[gc.TINT32]
}
// largest ullman on left.
if nl.Ullman < nr.Ullman {
tmp := nl
nl = nr
nr = tmp
}
var nt gc.Node
gc.Tempname(&nt, nl.Type)
cgen(nl, &nt)
var n1 gc.Node
regalloc(&n1, t, res)
cgen(nr, &n1)
var n2 gc.Node
regalloc(&n2, t, nil)
gmove(&nt, &n2)
a := optoas(op, t)
gins(a, &n2, &n1)
regfree(&n2)
gmove(&n1, res)
regfree(&n1)
}
作者:tidatid
项目:g
func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
r := int(reg[dr])
gc.Nodreg(x, gc.Types[gc.TINT32], dr)
// save current ax and dx if they are live
// and not the destination
*oldx = gc.Node{}
if r > 0 && !gc.Samereg(x, res) {
gc.Tempname(oldx, gc.Types[gc.TINT32])
gmove(x, oldx)
}
gc.Regalloc(x, t, x)
}
作者:kluesk
项目:go-akaro
/*
* generate function call;
* proc=0 normal call
* proc=1 goroutine run in new proc
* proc=2 defer call save away stack
*/
func cgen_call(n *gc.Node, proc int) {
if n == nil {
return
}
var afun gc.Node
if n.Left.Ullman >= gc.UINF {
// if name involves a fn call
// precompute the address of the fn
gc.Tempname(&afun, gc.Types[gc.Tptr])
cgen(n.Left, &afun)
}
gc.Genlist(n.List) // assign the args
t := n.Left.Type
// call tempname pointer
if n.Left.Ullman >= gc.UINF {
var nod gc.Node
regalloc(&nod, gc.Types[gc.Tptr], nil)
gc.Cgen_as(&nod, &afun)
nod.Type = t
ginscall(&nod, proc)
regfree(&nod)
return
}
// call pointer
if n.Left.Op != gc.ONAME || n.Left.Class != gc.PFUNC {
var nod gc.Node
regalloc(&nod, gc.Types[gc.Tptr], nil)
gc.Cgen_as(&nod, n.Left)
nod.Type = t
ginscall(&nod, proc)
regfree(&nod)
return
}
// call direct
n.Left.Method = 1
ginscall(n.Left, proc)
}
作者:tidatid
项目:g
/*
* generate floating-point operation.
*/
func cgen_float(n *gc.Node, res *gc.Node) {
nl := n.Left
switch n.Op {
case gc.OEQ,
gc.ONE,
gc.OLT,
gc.OLE,
gc.OGE:
p1 := gc.Gbranch(obj.AJMP, nil, 0)
p2 := gc.Pc
gmove(gc.Nodbool(true), res)
p3 := gc.Gbranch(obj.AJMP, nil, 0)
gc.Patch(p1, gc.Pc)
gc.Bgen(n, true, 0, p2)
gmove(gc.Nodbool(false), res)
gc.Patch(p3, gc.Pc)
return
case gc.OPLUS:
gc.Cgen(nl, res)
return
case gc.OCONV:
if gc.Eqtype(n.Type, nl.Type) || gc.Noconv(n.Type, nl.Type) {
gc.Cgen(nl, res)
return
}
var n2 gc.Node
gc.Tempname(&n2, n.Type)
var n1 gc.Node
gc.Mgen(nl, &n1, res)
gmove(&n1, &n2)
gmove(&n2, res)
gc.Mfree(&n1)
return
}
if gc.Thearch.Use387 {
cgen_float387(n, res)
} else {
cgen_floatsse(n, res)
}
}
作者:kluesk
项目:go-akaro
/*
* peep.c
*/
func mgen(n *gc.Node, n1 *gc.Node, rg *gc.Node) {
n1.Op = gc.OEMPTY
if n.Addable != 0 {
*n1 = *n
if n1.Op == gc.OREGISTER || n1.Op == gc.OINDREG {
reg[n.Val.U.Reg]++
}
return
}
gc.Tempname(n1, n.Type)
cgen(n, n1)
if n.Type.Width <= int64(gc.Widthptr) || gc.Isfloat[n.Type.Etype] {
n2 := *n1
regalloc(n1, n.Type, rg)
gmove(&n2, n1)
}
}
作者:tidatid
项目:g
/*
* generate high multiply:
* res = (nl*nr) >> width
*/
func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
var n2 gc.Node
var ax gc.Node
var dx gc.Node
t := nl.Type
a := optoas(gc.OHMUL, t)
// gen nl in n1.
gc.Tempname(&n1, t)
gc.Cgen(nl, &n1)
// gen nr in n2.
gc.Regalloc(&n2, t, res)
gc.Cgen(nr, &n2)
// multiply.
gc.Nodreg(&ax, t, x86.REG_AX)
gmove(&n2, &ax)
gins(a, &n1, nil)
gc.Regfree(&n2)
if t.Width == 1 {
// byte multiply behaves differently.
gc.Nodreg(&ax, t, x86.REG_AH)
gc.Nodreg(&dx, t, x86.REG_DX)
gmove(&ax, &dx)
}
gc.Nodreg(&dx, t, x86.REG_DX)
gmove(&dx, res)
}
作者:xslonepiec
项目:goio
func memname(n *gc.Node, t *gc.Type) {
gc.Tempname(n, t)
n.Sym = gc.Lookup("." + n.Sym.Name[1:]) // keep optimizer from registerizing
n.Orig.Sym = n.Sym
}
作者:xslonepiec
项目:goio
//.........这里部分代码省略.........
gc.TFLOAT64<<16 | gc.TINT8,
gc.TFLOAT64<<16 | gc.TUINT16,
gc.TFLOAT64<<16 | gc.TUINT8:
cvt = gc.Types[gc.TINT32]
goto hard
// convert via int64.
case gc.TFLOAT32<<16 | gc.TUINT32,
gc.TFLOAT64<<16 | gc.TUINT32:
cvt = gc.Types[gc.TINT64]
goto hardmem
case gc.TFLOAT32<<16 | gc.TINT32:
a = x86.ACVTTSS2SL
goto rdst
case gc.TFLOAT64<<16 | gc.TINT32:
a = x86.ACVTTSD2SL
goto rdst
// convert via int32 memory
/*
* integer to float
*/
case gc.TINT8<<16 | gc.TFLOAT32,
gc.TINT8<<16 | gc.TFLOAT64,
gc.TINT16<<16 | gc.TFLOAT32,
gc.TINT16<<16 | gc.TFLOAT64,
gc.TUINT16<<16 | gc.TFLOAT32,
gc.TUINT16<<16 | gc.TFLOAT64,
gc.TUINT8<<16 | gc.TFLOAT32,
gc.TUINT8<<16 | gc.TFLOAT64:
cvt = gc.Types[gc.TINT32]
goto hard
// convert via int64 memory
case gc.TUINT32<<16 | gc.TFLOAT32,
gc.TUINT32<<16 | gc.TFLOAT64:
cvt = gc.Types[gc.TINT64]
goto hardmem
case gc.TINT32<<16 | gc.TFLOAT32:
a = x86.ACVTSL2SS
goto rdst
case gc.TINT32<<16 | gc.TFLOAT64:
a = x86.ACVTSL2SD
goto rdst
/*
* float to float
*/
case gc.TFLOAT32<<16 | gc.TFLOAT32:
a = x86.AMOVSS
case gc.TFLOAT64<<16 | gc.TFLOAT64:
a = x86.AMOVSD
case gc.TFLOAT32<<16 | gc.TFLOAT64:
a = x86.ACVTSS2SD
goto rdst
case gc.TFLOAT64<<16 | gc.TFLOAT32:
a = x86.ACVTSD2SS
goto rdst
}
gins(a, f, t)
return
// requires register intermediate
hard:
gc.Regalloc(&r1, cvt, t)
gmove(f, &r1)
gmove(&r1, t)
gc.Regfree(&r1)
return
// requires memory intermediate
hardmem:
gc.Tempname(&r1, cvt)
gmove(f, &r1)
gmove(&r1, t)
return
// requires register destination
rdst:
gc.Regalloc(&r1, t.Type, t)
gins(a, f, &r1)
gmove(&r1, t)
gc.Regfree(&r1)
return
}
作者:xslonepiec
项目:goio
func floatmove_387(f *gc.Node, t *gc.Node) {
var r1 gc.Node
var a int
ft := gc.Simsimtype(f.Type)
tt := gc.Simsimtype(t.Type)
cvt := t.Type
switch uint32(ft)<<16 | uint32(tt) {
default:
goto fatal
/*
* float to integer
*/
case gc.TFLOAT32<<16 | gc.TINT16,
gc.TFLOAT32<<16 | gc.TINT32,
gc.TFLOAT32<<16 | gc.TINT64,
gc.TFLOAT64<<16 | gc.TINT16,
gc.TFLOAT64<<16 | gc.TINT32,
gc.TFLOAT64<<16 | gc.TINT64:
if t.Op == gc.OREGISTER {
goto hardmem
}
var r1 gc.Node
gc.Nodreg(&r1, gc.Types[ft], x86.REG_F0)
if f.Op != gc.OREGISTER {
if ft == gc.TFLOAT32 {
gins(x86.AFMOVF, f, &r1)
} else {
gins(x86.AFMOVD, f, &r1)
}
}
// set round to zero mode during conversion
var t1 gc.Node
memname(&t1, gc.Types[gc.TUINT16])
var t2 gc.Node
memname(&t2, gc.Types[gc.TUINT16])
gins(x86.AFSTCW, nil, &t1)
gins(x86.AMOVW, ncon(0xf7f), &t2)
gins(x86.AFLDCW, &t2, nil)
if tt == gc.TINT16 {
gins(x86.AFMOVWP, &r1, t)
} else if tt == gc.TINT32 {
gins(x86.AFMOVLP, &r1, t)
} else {
gins(x86.AFMOVVP, &r1, t)
}
gins(x86.AFLDCW, &t1, nil)
return
// convert via int32.
case gc.TFLOAT32<<16 | gc.TINT8,
gc.TFLOAT32<<16 | gc.TUINT16,
gc.TFLOAT32<<16 | gc.TUINT8,
gc.TFLOAT64<<16 | gc.TINT8,
gc.TFLOAT64<<16 | gc.TUINT16,
gc.TFLOAT64<<16 | gc.TUINT8:
var t1 gc.Node
gc.Tempname(&t1, gc.Types[gc.TINT32])
gmove(f, &t1)
switch tt {
default:
gc.Fatal("gmove %v", gc.Nconv(t, 0))
case gc.TINT8:
gins(x86.ACMPL, &t1, ncon(-0x80&(1<<32-1)))
p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TINT32]), nil, -1)
gins(x86.ACMPL, &t1, ncon(0x7f))
p2 := gc.Gbranch(optoas(gc.OGT, gc.Types[gc.TINT32]), nil, -1)
p3 := gc.Gbranch(obj.AJMP, nil, 0)
gc.Patch(p1, gc.Pc)
gc.Patch(p2, gc.Pc)
gmove(ncon(-0x80&(1<<32-1)), &t1)
gc.Patch(p3, gc.Pc)
gmove(&t1, t)
case gc.TUINT8:
gins(x86.ATESTL, ncon(0xffffff00), &t1)
p1 := gc.Gbranch(x86.AJEQ, nil, +1)
gins(x86.AMOVL, ncon(0), &t1)
gc.Patch(p1, gc.Pc)
gmove(&t1, t)
case gc.TUINT16:
gins(x86.ATESTL, ncon(0xffff0000), &t1)
p1 := gc.Gbranch(x86.AJEQ, nil, +1)
gins(x86.AMOVL, ncon(0), &t1)
gc.Patch(p1, gc.Pc)
gmove(&t1, t)
}
return
// convert via int64.
case gc.TFLOAT32<<16 | gc.TUINT32,
gc.TFLOAT64<<16 | gc.TUINT32:
//.........这里部分代码省略.........
作者:xslonepiec
项目:goio
//.........这里部分代码省略.........
return
/*
* integer to float
*/
case gc.TINT64<<16 | gc.TFLOAT32,
gc.TINT64<<16 | gc.TFLOAT64:
if t.Op == gc.OREGISTER {
goto hardmem
}
var f0 gc.Node
gc.Nodreg(&f0, t.Type, x86.REG_F0)
gins(x86.AFMOVV, f, &f0)
if tt == gc.TFLOAT32 {
gins(x86.AFMOVFP, &f0, t)
} else {
gins(x86.AFMOVDP, &f0, t)
}
return
// algorithm is:
// if small enough, use native int64 -> float64 conversion.
// otherwise, halve (rounding to odd?), convert, and double.
case gc.TUINT64<<16 | gc.TFLOAT32,
gc.TUINT64<<16 | gc.TFLOAT64:
var ax gc.Node
gc.Nodreg(&ax, gc.Types[gc.TUINT32], x86.REG_AX)
var dx gc.Node
gc.Nodreg(&dx, gc.Types[gc.TUINT32], x86.REG_DX)
var cx gc.Node
gc.Nodreg(&cx, gc.Types[gc.TUINT32], x86.REG_CX)
var t1 gc.Node
gc.Tempname(&t1, f.Type)
var tlo gc.Node
var thi gc.Node
split64(&t1, &tlo, &thi)
gmove(f, &t1)
gins(x86.ACMPL, &thi, ncon(0))
p1 := gc.Gbranch(x86.AJLT, nil, 0)
// native
var r1 gc.Node
gc.Nodreg(&r1, gc.Types[tt], x86.REG_F0)
gins(x86.AFMOVV, &t1, &r1)
if tt == gc.TFLOAT32 {
gins(x86.AFMOVFP, &r1, t)
} else {
gins(x86.AFMOVDP, &r1, t)
}
p2 := gc.Gbranch(obj.AJMP, nil, 0)
// simulated
gc.Patch(p1, gc.Pc)
gmove(&tlo, &ax)
gmove(&thi, &dx)
p1 = gins(x86.ASHRL, ncon(1), &ax)
p1.From.Index = x86.REG_DX // double-width shift DX -> AX
p1.From.Scale = 0
gins(x86.AMOVL, ncon(0), &cx)
gins(x86.ASETCC, nil, &cx)
gins(x86.AORL, &cx, &ax)
gins(x86.ASHRL, ncon(1), &dx)
gmove(&dx, &thi)
作者:bibbyflyawa
项目:g
func igenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
gc.Tempname(res, n.Type)
return cgenindex(n, res, bounded)
}
作者:tidatid
项目:g
func cgen_floatsse(n *gc.Node, res *gc.Node) {
var a int
nl := n.Left
nr := n.Right
switch n.Op {
default:
gc.Dump("cgen_floatsse", n)
gc.Fatal("cgen_floatsse %v", gc.Oconv(int(n.Op), 0))
return
case gc.OMINUS,
gc.OCOM:
nr = gc.Nodintconst(-1)
gc.Convlit(&nr, n.Type)
a = foptoas(gc.OMUL, nl.Type, 0)
goto sbop
// symmetric binary
case gc.OADD,
gc.OMUL:
a = foptoas(int(n.Op), nl.Type, 0)
goto sbop
// asymmetric binary
case gc.OSUB,
gc.OMOD,
gc.ODIV:
a = foptoas(int(n.Op), nl.Type, 0)
goto abop
}
sbop: // symmetric binary
if nl.Ullman < nr.Ullman || nl.Op == gc.OLITERAL {
r := nl
nl = nr
nr = r
}
abop: // asymmetric binary
if nl.Ullman >= nr.Ullman {
var nt gc.Node
gc.Tempname(&nt, nl.Type)
gc.Cgen(nl, &nt)
var n2 gc.Node
gc.Mgen(nr, &n2, nil)
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gmove(&nt, &n1)
gins(a, &n2, &n1)
gmove(&n1, res)
gc.Regfree(&n1)
gc.Mfree(&n2)
} else {
var n2 gc.Node
gc.Regalloc(&n2, nr.Type, res)
gc.Cgen(nr, &n2)
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, nil)
gc.Cgen(nl, &n1)
gins(a, &n2, &n1)
gc.Regfree(&n2)
gmove(&n1, res)
gc.Regfree(&n1)
}
return
}
作者:kluesk
项目:go-akaro
/*
* generate shift according to op, one of:
* res = nl << nr
* res = nl >> nr
*/
func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
a := int(optoas(op, nl.Type))
if nr.Op == gc.OLITERAL {
var n1 gc.Node
regalloc(&n1, nl.Type, res)
cgen(nl, &n1)
sc := uint64(uint64(gc.Mpgetfix(nr.Val.U.Xval)))
if sc >= uint64(nl.Type.Width*8) {
// large shift gets 2 shifts by width-1
var n3 gc.Node
gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
gins(a, &n3, &n1)
gins(a, &n3, &n1)
} else {
gins(a, nr, &n1)
}
gmove(&n1, res)
regfree(&n1)
return
}
if nl.Ullman >= gc.UINF {
var n4 gc.Node
gc.Tempname(&n4, nl.Type)
cgen(nl, &n4)
nl = &n4
}
if nr.Ullman >= gc.UINF {
var n5 gc.Node
gc.Tempname(&n5, nr.Type)
cgen(nr, &n5)
nr = &n5
}
// Allow either uint32 or uint64 as shift type,
// to avoid unnecessary conversion from uint32 to uint64
// just to do the comparison.
tcount := gc.Types[gc.Simtype[nr.Type.Etype]]
if tcount.Etype < gc.TUINT32 {
tcount = gc.Types[gc.TUINT32]
}
var n1 gc.Node
regalloc(&n1, nr.Type, nil) // to hold the shift type in CX
var n3 gc.Node
regalloc(&n3, tcount, &n1) // to clear high bits of CX
var n2 gc.Node
regalloc(&n2, nl.Type, res)
if nl.Ullman >= nr.Ullman {
cgen(nl, &n2)
cgen(nr, &n1)
gmove(&n1, &n3)
} else {
cgen(nr, &n1)
gmove(&n1, &n3)
cgen(nl, &n2)
}
regfree(&n3)
// test and fix up large shifts
if !bounded {
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))
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)
} else {
gc.Nodconst(&n3, nl.Type, 0)
gmove(&n3, &n2)
}
gc.Patch(p1, gc.Pc)
}
gins(a, &n1, &n2)
gmove(&n2, res)
regfree(&n1)
regfree(&n2)
}
作者:kluesk
项目:go-akaro
//.........这里部分代码省略.........
}
}
gc.Flusherrors()
for i := int(arm64.REG_R0); i < arm64.REG_R0+arm64.NREG; i++ {
fmt.Printf("R%d %p\n", i, regpc[i-arm64.REG_R0])
}
gc.Fatal("out of fixed registers")
case gc.TFLOAT32,
gc.TFLOAT64:
if o != nil && o.Op == gc.OREGISTER {
i = int(o.Val.U.Reg)
if i >= arm64.FREGMIN && i <= arm64.FREGMAX {
goto out
}
}
for i = arm64.FREGMIN; i <= arm64.FREGMAX; i++ {
if reg[i-arm64.REG_R0] == 0 {
regpc[i-arm64.REG_R0] = uint32(obj.Getcallerpc(&n))
goto out
}
}
gc.Flusherrors()
for i := int(arm64.REG_F0); i < arm64.REG_F0+arm64.NREG; i++ {
fmt.Printf("F%d %p\n", i, regpc[i-arm64.REG_R0])
}
gc.Fatal("out of floating registers")
case gc.TCOMPLEX64,
gc.TCOMPLEX128:
gc.Tempname(n, t)
return
}
gc.Fatal("regalloc: unknown type %v", gc.Tconv(t, 0))
return
out:
reg[i-arm64.REG_R0]++
gc.Nodreg(n, t, i)
}
func regfree(n *gc.Node) {
if n.Op == gc.ONAME {
return
}
if n.Op != gc.OREGISTER && n.Op != gc.OINDREG {
gc.Fatal("regfree: not a register")
}
i := int(int(n.Val.U.Reg) - arm64.REG_R0)
if i == arm64.REGSP-arm64.REG_R0 {
return
}
if i < 0 || i >= len(reg) {
gc.Fatal("regfree: reg out of range")
}
if reg[i] <= 0 {
gc.Fatal("regfree: reg not allocated")
}
reg[i]--
if reg[i] == 0 {
regpc[i] = 0
}
作者:kluesk
项目:go-akaro
//.........这里部分代码省略.........
var n2 gc.Node
regalloc(&n2, gc.Types[gc.Tptr], &n1)
gmove(&n1, &n2)
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
regfree(&n2)
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
regfree(&n1)
break
}
if gc.Isinter(nl.Type) {
// front end should only leave cmp to literal nil
if (a != gc.OEQ && a != gc.ONE) || nr.Op != gc.OLITERAL {
gc.Yyerror("illegal interface comparison")
break
}
a = optoas(a, gc.Types[gc.Tptr])
var n1 gc.Node
igen(nl, &n1, nil)
n1.Type = gc.Types[gc.Tptr]
var tmp gc.Node
gc.Nodconst(&tmp, gc.Types[gc.Tptr], 0)
var n2 gc.Node
regalloc(&n2, gc.Types[gc.Tptr], &n1)
gmove(&n1, &n2)
gins(optoas(gc.OCMP, gc.Types[gc.Tptr]), &n2, &tmp)
regfree(&n2)
gc.Patch(gc.Gbranch(a, gc.Types[gc.Tptr], likely), to)
regfree(&n1)
break
}
if gc.Iscomplex[nl.Type.Etype] {
gc.Complexbool(a, nl, nr, true_, likely, to)
break
}
var n1 gc.Node
var n2 gc.Node
if nr.Ullman >= gc.UINF {
regalloc(&n1, nl.Type, nil)
cgen(nl, &n1)
var tmp gc.Node
gc.Tempname(&tmp, nl.Type)
gmove(&n1, &tmp)
regfree(&n1)
regalloc(&n2, nr.Type, nil)
cgen(nr, &n2)
regalloc(&n1, nl.Type, nil)
cgen(&tmp, &n1)
goto cmp
}
regalloc(&n1, nl.Type, nil)
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)
cgen(nr, &n2)
cmp:
l := &n1
r := &n2
gins(optoas(gc.OCMP, nr.Type), l, r)
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.
switch a {
case gc.OLE:
a = gc.OLT
case gc.OGE:
a = gc.OGT
}
gc.Patch(gc.Gbranch(optoas(a, nr.Type), nr.Type, likely), to)
gc.Patch(gc.Gbranch(optoas(gc.OEQ, nr.Type), nr.Type, likely), to)
} else {
gc.Patch(gc.Gbranch(optoas(a, nr.Type), nr.Type, likely), to)
}
regfree(&n1)
regfree(&n2)
}
return
}
作者:tidatid
项目:g
func stackcopy(n, res *gc.Node, osrc, odst, w int64) {
var dst gc.Node
gc.Nodreg(&dst, gc.Types[gc.Tptr], x86.REG_DI)
var src gc.Node
gc.Nodreg(&src, gc.Types[gc.Tptr], x86.REG_SI)
var tsrc gc.Node
gc.Tempname(&tsrc, gc.Types[gc.Tptr])
var tdst gc.Node
gc.Tempname(&tdst, gc.Types[gc.Tptr])
if n.Addable == 0 {
gc.Agen(n, &tsrc)
}
if res.Addable == 0 {
gc.Agen(res, &tdst)
}
if n.Addable != 0 {
gc.Agen(n, &src)
} else {
gmove(&tsrc, &src)
}
if res.Op == gc.ONAME {
gc.Gvardef(res)
}
if res.Addable != 0 {
gc.Agen(res, &dst)
} else {
gmove(&tdst, &dst)
}
c := int32(w % 4) // bytes
q := int32(w / 4) // doublewords
// if we are copying forward on the stack and
// the src and dst overlap, then reverse direction
if osrc < odst && int64(odst) < int64(osrc)+w {
// reverse direction
gins(x86.ASTD, nil, nil) // set direction flag
if c > 0 {
gconreg(x86.AADDL, w-1, x86.REG_SI)
gconreg(x86.AADDL, w-1, x86.REG_DI)
gconreg(x86.AMOVL, int64(c), x86.REG_CX)
gins(x86.AREP, nil, nil) // repeat
gins(x86.AMOVSB, nil, nil) // MOVB *(SI)-,*(DI)-
}
if q > 0 {
if c > 0 {
gconreg(x86.AADDL, -3, x86.REG_SI)
gconreg(x86.AADDL, -3, x86.REG_DI)
} else {
gconreg(x86.AADDL, w-4, x86.REG_SI)
gconreg(x86.AADDL, w-4, x86.REG_DI)
}
gconreg(x86.AMOVL, int64(q), x86.REG_CX)
gins(x86.AREP, nil, nil) // repeat
gins(x86.AMOVSL, nil, nil) // MOVL *(SI)-,*(DI)-
}
// we leave with the flag clear
gins(x86.ACLD, nil, nil)
} else {
gins(x86.ACLD, nil, nil) // paranoia. TODO(rsc): remove?
// normal direction
if q > 128 || (q >= 4 && gc.Nacl) {
gconreg(x86.AMOVL, int64(q), x86.REG_CX)
gins(x86.AREP, nil, nil) // repeat
gins(x86.AMOVSL, nil, nil) // MOVL *(SI)+,*(DI)+
} else if q >= 4 {
p := gins(obj.ADUFFCOPY, nil, nil)
p.To.Type = obj.TYPE_ADDR
p.To.Sym = gc.Linksym(gc.Pkglookup("duffcopy", gc.Runtimepkg))
// 10 and 128 = magic constants: see ../../runtime/asm_386.s
p.To.Offset = 10 * (128 - int64(q))
} else if !gc.Nacl && c == 0 {
var cx gc.Node
gc.Nodreg(&cx, gc.Types[gc.TINT32], x86.REG_CX)
// We don't need the MOVSL side-effect of updating SI and DI,
// and issuing a sequence of MOVLs directly is faster.
src.Op = gc.OINDREG
dst.Op = gc.OINDREG
for q > 0 {
gmove(&src, &cx) // MOVL x+(SI),CX
gmove(&cx, &dst) // MOVL CX,x+(DI)
src.Xoffset += 4
dst.Xoffset += 4
q--
}
} else {
for q > 0 {
gins(x86.AMOVSL, nil, nil) // MOVL *(SI)+,*(DI)+
q--
//.........这里部分代码省略.........
作者:xslonepiec
项目:goio
/*
* attempt to generate 64-bit
* res = n
* return 1 on success, 0 if op not handled.
*/
func cgen64(n *gc.Node, res *gc.Node) {
if res.Op != gc.OINDREG && res.Op != gc.ONAME {
gc.Dump("n", n)
gc.Dump("res", res)
gc.Fatal("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
}
switch n.Op {
default:
gc.Fatal("cgen64 %v", gc.Oconv(int(n.Op), 0))
case gc.OMINUS:
gc.Cgen(n.Left, res)
var hi1 gc.Node
var lo1 gc.Node
split64(res, &lo1, &hi1)
gins(x86.ANEGL, nil, &lo1)
gins(x86.AADCL, ncon(0), &hi1)
gins(x86.ANEGL, nil, &hi1)
splitclean()
return
case gc.OCOM:
gc.Cgen(n.Left, res)
var lo1 gc.Node
var hi1 gc.Node
split64(res, &lo1, &hi1)
gins(x86.ANOTL, nil, &lo1)
gins(x86.ANOTL, nil, &hi1)
splitclean()
return
// binary operators.
// common setup below.
case gc.OADD,
gc.OSUB,
gc.OMUL,
gc.OLROT,
gc.OLSH,
gc.ORSH,
gc.OAND,
gc.OOR,
gc.OXOR:
break
}
l := n.Left
r := n.Right
if !l.Addable {
var t1 gc.Node
gc.Tempname(&t1, l.Type)
gc.Cgen(l, &t1)
l = &t1
}
if r != nil && !r.Addable {
var t2 gc.Node
gc.Tempname(&t2, r.Type)
gc.Cgen(r, &t2)
r = &t2
}
var ax gc.Node
gc.Nodreg(&ax, gc.Types[gc.TINT32], x86.REG_AX)
var cx gc.Node
gc.Nodreg(&cx, gc.Types[gc.TINT32], x86.REG_CX)
var dx gc.Node
gc.Nodreg(&dx, gc.Types[gc.TINT32], x86.REG_DX)
// Setup for binary operation.
var hi1 gc.Node
var lo1 gc.Node
split64(l, &lo1, &hi1)
var lo2 gc.Node
var hi2 gc.Node
if gc.Is64(r.Type) {
split64(r, &lo2, &hi2)
}
// Do op. Leave result in DX:AX.
switch n.Op {
// TODO: Constants
case gc.OADD:
gins(x86.AMOVL, &lo1, &ax)
gins(x86.AMOVL, &hi1, &dx)
gins(x86.AADDL, &lo2, &ax)
gins(x86.AADCL, &hi2, &dx)
// TODO: Constants.
case gc.OSUB:
gins(x86.AMOVL, &lo1, &ax)
gins(x86.AMOVL, &hi1, &dx)
//.........这里部分代码省略.........
作者:bibbyflyawa
项目:g
/*
* generate shift according to op, one of:
* res = nl << nr
* res = nl >> nr
*/
func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
if nl.Type.Width > 4 {
gc.Fatal("cgen_shift %v", nl.Type)
}
w := int(nl.Type.Width * 8)
if op == gc.OLROT {
v := nr.Int()
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
if w == 32 {
gc.Cgen(nl, &n1)
gshift(arm.AMOVW, &n1, arm.SHIFT_RR, int32(w)-int32(v), &n1)
} else {
var n2 gc.Node
gc.Regalloc(&n2, nl.Type, nil)
gc.Cgen(nl, &n2)
gshift(arm.AMOVW, &n2, arm.SHIFT_LL, int32(v), &n1)
gshift(arm.AORR, &n2, arm.SHIFT_LR, int32(w)-int32(v), &n1)
gc.Regfree(&n2)
// Ensure sign/zero-extended result.
gins(optoas(gc.OAS, nl.Type), &n1, &n1)
}
gmove(&n1, res)
gc.Regfree(&n1)
return
}
if nr.Op == gc.OLITERAL {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gc.Cgen(nl, &n1)
sc := uint64(nr.Int())
if sc == 0 {
} else // nothing to do
if sc >= uint64(nl.Type.Width*8) {
if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
gshift(arm.AMOVW, &n1, arm.SHIFT_AR, int32(w), &n1)
} else {
gins(arm.AEOR, &n1, &n1)
}
} else {
if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
gshift(arm.AMOVW, &n1, arm.SHIFT_AR, int32(sc), &n1)
} else if op == gc.ORSH {
gshift(arm.AMOVW, &n1, arm.SHIFT_LR, int32(sc), &n1) // OLSH
} else {
gshift(arm.AMOVW, &n1, arm.SHIFT_LL, int32(sc), &n1)
}
}
if w < 32 && op == gc.OLSH {
gins(optoas(gc.OAS, nl.Type), &n1, &n1)
}
gmove(&n1, res)
gc.Regfree(&n1)
return
}
tr := nr.Type
var t gc.Node
var n1 gc.Node
var n2 gc.Node
var n3 gc.Node
if tr.Width > 4 {
var nt gc.Node
gc.Tempname(&nt, nr.Type)
if nl.Ullman >= nr.Ullman {
gc.Regalloc(&n2, nl.Type, res)
gc.Cgen(nl, &n2)
gc.Cgen(nr, &nt)
n1 = nt
} else {
gc.Cgen(nr, &nt)
gc.Regalloc(&n2, nl.Type, res)
gc.Cgen(nl, &n2)
}
var hi gc.Node
var lo gc.Node
split64(&nt, &lo, &hi)
gc.Regalloc(&n1, gc.Types[gc.TUINT32], nil)
gc.Regalloc(&n3, gc.Types[gc.TUINT32], nil)
gmove(&lo, &n1)
gmove(&hi, &n3)
splitclean()
gins(arm.ATST, &n3, nil)
gc.Nodconst(&t, gc.Types[gc.TUINT32], int64(w))
p1 := gins(arm.AMOVW, &t, &n1)
p1.Scond = arm.C_SCOND_NE
tr = gc.Types[gc.TUINT32]
gc.Regfree(&n3)
//.........这里部分代码省略.........