作者:duhaibo040
项目:go-
// as2variant returns the variant (V_*) flags of instruction as.
func as2variant(as obj.As) int {
for i, v := range varianttable[as&obj.AMask] {
if v&obj.AMask == as&obj.AMask {
return i
}
}
gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as&obj.AMask))
return 0
}
作者:danny800
项目:g
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1:][0]
}
a1 = int(p.From.Class)
if a1 == 0 {
a1 = aclass(ctxt, &p.From) + 1
p.From.Class = int8(a1)
}
a1--
a3 := int(p.To.Class)
if a3 == 0 {
a3 = aclass(ctxt, &p.To) + 1
p.To.Class = int8(a3)
}
a3--
a2 := C_NONE
if p.Reg != 0 {
a2 = C_REG
}
//print("oplook %P %d %d %d\n", p, a1, a2, a3);
r0 := p.As & obj.AMask
o := oprange[r0].start
if o == nil {
o = oprange[r0].stop /* just generate an error */
}
e := oprange[r0].stop
c1 := xcmp[a1][:]
c3 := xcmp[a3][:]
for ; -cap(o) < -cap(e); o = o[1:] {
if int(o[0].a2) == a2 {
if c1[o[0].a1] != 0 {
if c3[o[0].a3] != 0 {
p.Optab = uint16((-cap(o) + cap(optab)) + 1)
return &o[0]
}
}
}
}
ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if o == nil {
o = optab
}
return &o[0]
}
作者:ckeye
项目:gosr
// 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.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as))
return 0
}
作者:2theto
项目:g
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
if oprange[AOR&obj.AMask] == nil {
buildop(ctxt)
}
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1]
}
a1 = int(p.From.Class)
if a1 == 0 {
a1 = aclass(ctxt, &p.From) + 1
p.From.Class = int8(a1)
}
a1--
a3 := int(p.To.Class)
if a3 == 0 {
a3 = aclass(ctxt, &p.To) + 1
p.To.Class = int8(a3)
}
a3--
a2 := C_NONE
if p.Reg != 0 {
a2 = C_REG
}
//print("oplook %P %d %d %d\n", p, a1, a2, a3);
ops := oprange[p.As&obj.AMask]
c1 := &xcmp[a1]
c3 := &xcmp[a3]
for i := range ops {
op := &ops[i]
if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
return op
}
}
ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if ops == nil {
ops = optab
}
return &ops[0]
}
作者:xiezerozer
项目:g
/*
* shortprop eliminates redundant zero/sign extensions.
*
* MOVBS x, R
* <no use R>
* MOVBS R, R'
*
* changed to
*
* MOVBS x, R
* ...
* MOVB R, R' (compiled to mov)
*
* MOVBS above can be a MOVBS, MOVBU, MOVHS or MOVHU.
*/
func shortprop(r *gc.Flow) bool {
p := (*obj.Prog)(r.Prog)
r1 := (*gc.Flow)(findpre(r, &p.From))
if r1 == nil {
return false
}
p1 := (*obj.Prog)(r1.Prog)
if p1.As == p.As {
// Two consecutive extensions.
goto gotit
}
if p1.As == arm.AMOVW && isdconst(&p1.From) && p1.From.Offset >= 0 && p1.From.Offset < 128 {
// Loaded an immediate.
goto gotit
}
return false
gotit:
if gc.Debug['P'] != 0 {
fmt.Printf("shortprop\n%v\n%v", p1, p)
}
switch p.As {
case arm.AMOVBS,
arm.AMOVBU:
p.As = arm.AMOVB
case arm.AMOVHS,
arm.AMOVHU:
p.As = arm.AMOVH
}
if gc.Debug['P'] != 0 {
fmt.Printf(" => %v\n", obj.Aconv(int(p.As)))
}
return true
}
作者:duhaibo040
项目:go-
//.........这里部分代码省略.........
return AJNE
case AJNE:
return AJEQ
case AJLE:
return AJGT
case AJLS:
return AJHI
case AJLT:
return AJGE
case AJMI:
return AJPL
case AJGE:
return AJLT
case AJPL:
return AJMI
case AJGT:
return AJLE
case AJHI:
return AJLS
case AJCS:
return AJCC
case AJCC:
return AJCS
case AJPS:
return AJPC
case AJPC:
return AJPS
case AJOS:
return AJOC
case AJOC:
return AJOS
}
log.Fatalf("unknown relation: %s", obj.Aconv(a))
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var i int
var a obj.As
loop:
if p == nil {
return
}
if p.As == obj.AJMP {
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
/* mark instruction as done and continue layout at target of jump */
p.Mark |= DONE
p = q
if p.Mark&DONE == 0 {
goto loop
}
}
}
if p.Mark&DONE != 0 {
/*
* p goes here, but already used it elsewhere.
* copy up to 4 instructions or else branch to other copy.
*/
i = 0
q = p
作者:noscripte
项目:g
// getRegister checks that addr represents a register and returns its value.
func (p *Parser) getRegister(prog *obj.Prog, op int, addr *obj.Addr) int16 {
if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {
p.errorf("%s: expected register; found %s", obj.Aconv(op), obj.Dconv(prog, addr))
}
return addr.Reg
}
作者:noscripte
项目:g
// getImmediate checks that addr represents an immediate constant and returns its value.
func (p *Parser) getImmediate(prog *obj.Prog, op int, addr *obj.Addr) int64 {
if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
p.errorf("%s: expected immediate constant; found %s", obj.Aconv(op), obj.Dconv(prog, addr))
}
return addr.Offset
}
作者:noscripte
项目:g
// asmInstruction assembles an instruction.
// MOVW R9, (R10)
func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
// fmt.Printf("%s %+v\n", obj.Aconv(op), a)
prog := &obj.Prog{
Ctxt: p.ctxt,
Lineno: p.histLineNum,
As: int16(op),
}
switch len(a) {
case 0:
// Nothing to do.
case 1:
if p.arch.UnaryDst[op] {
// prog.From is no address.
prog.To = a[0]
} else {
prog.From = a[0]
// prog.To is no address.
}
if p.arch.Thechar == '9' && arch.IsPPC64NEG(op) {
// NEG: From and To are both a[0].
prog.To = a[0]
prog.From = a[0]
break
}
case 2:
if p.arch.Thechar == '5' {
if arch.IsARMCMP(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
// Strange special cases.
if arch.IsARMSTREX(op) {
/*
STREX x, (y)
from=(y) reg=x to=x
STREX (x), y
from=(x) reg=y to=y
*/
if a[0].Type == obj.TYPE_REG && a[1].Type != obj.TYPE_REG {
prog.From = a[1]
prog.Reg = a[0].Reg
prog.To = a[0]
break
} else if a[0].Type != obj.TYPE_REG && a[1].Type == obj.TYPE_REG {
prog.From = a[0]
prog.Reg = a[1].Reg
prog.To = a[1]
break
}
p.errorf("unrecognized addressing for %s", obj.Aconv(op))
return
}
if arch.IsARMFloatCmp(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
} else if p.arch.Thechar == '7' && arch.IsARM64CMP(op) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
}
prog.From = a[0]
prog.To = a[1]
case 3:
switch p.arch.Thechar {
case '5':
// Special cases.
if arch.IsARMSTREX(op) {
/*
STREX x, (y), z
from=(y) reg=x to=z
*/
prog.From = a[1]
prog.Reg = p.getRegister(prog, op, &a[0])
prog.To = a[2]
break
}
// Otherwise the 2nd operand (a[1]) must be a register.
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
case '7':
// ARM64 instructions with one input and two outputs.
if arch.IsARM64STLXR(op) {
prog.From = a[0]
prog.To = a[1]
if a[2].Type != obj.TYPE_REG {
p.errorf("invalid addressing modes for third operand to %s instruction, must be register", obj.Aconv(op))
return
}
prog.RegTo2 = a[2].Reg
break
}
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
//.........这里部分代码省略.........
作者:noscripte
项目:g
// asmJump assembles a jump instruction.
// JMP R1
// JMP exit
// JMP 3(PC)
func (p *Parser) asmJump(op int, cond string, a []obj.Addr) {
var target *obj.Addr
prog := &obj.Prog{
Ctxt: p.ctxt,
Lineno: p.histLineNum,
As: int16(op),
}
switch len(a) {
case 1:
target = &a[0]
case 2:
// Special 2-operand jumps.
target = &a[1]
prog.From = a[0]
case 3:
if p.arch.Thechar == '9' {
// Special 3-operand jumps.
// First two must be constants; a[1] is a register number.
target = &a[2]
prog.From = obj.Addr{
Type: obj.TYPE_CONST,
Offset: p.getConstant(prog, op, &a[0]),
}
reg := int16(p.getConstant(prog, op, &a[1]))
reg, ok := p.arch.RegisterNumber("R", int16(reg))
if !ok {
p.errorf("bad register number %d", reg)
return
}
prog.Reg = reg
break
}
fallthrough
default:
p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op))
return
}
switch {
case target.Type == obj.TYPE_BRANCH:
// JMP 4(PC)
prog.To = obj.Addr{
Type: obj.TYPE_BRANCH,
Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in append, below.
}
case target.Type == obj.TYPE_REG:
// JMP R1
prog.To = *target
case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
// JMP main·morestack(SB)
prog.To = *target
case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
// JMP *main·morestack(SB)
prog.To = *target
prog.To.Type = obj.TYPE_INDIR
case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
// JMP exit
if target.Sym == nil {
// Parse error left name unset.
return
}
targetProg := p.labels[target.Sym.Name]
if targetProg == nil {
p.toPatch = append(p.toPatch, Patch{prog, target.Sym.Name})
} else {
p.branch(prog, targetProg)
}
case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
// JMP 4(R0)
prog.To = *target
// On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.
if p.arch.Thechar == '9' && target.Offset == 0 {
prog.To.Type = obj.TYPE_REG
}
case target.Type == obj.TYPE_CONST:
// JMP $4
prog.To = a[0]
default:
p.errorf("cannot assemble jump %+v", target)
return
}
p.append(prog, cond, true)
}
作者:duhaibo040
项目:go-
// getConstant checks that addr represents a plain constant and returns its value.
func (p *Parser) getConstant(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
p.errorf("%s: expected integer constant; found %s", obj.Aconv(op), obj.Dconv(prog, addr))
}
return addr.Offset
}
作者:wycharr
项目:g
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE && p.From3Type() != obj.TYPE_CONST {
// Currently we never generate a From3 with anything other than a constant in it.
fmt.Printf("copyu: From3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
s390x.AMOVH,
s390x.AMOVHZ,
s390x.AMOVB,
s390x.AMOVBZ,
s390x.AMOVW,
s390x.AMOVWZ,
s390x.AMOVD,
s390x.ANEG,
s390x.AADDME,
s390x.AADDZE,
s390x.ASUBME,
s390x.ASUBZE,
s390x.AFMOVS,
s390x.AFMOVD,
s390x.AFRSP,
s390x.AFNEG,
s390x.ALDEBR,
s390x.ACLFEBR,
s390x.ACLGEBR,
s390x.ACLFDBR,
s390x.ACLGDBR,
s390x.ACFEBRA,
s390x.ACGEBRA,
s390x.ACFDBRA,
s390x.ACGDBRA,
s390x.ACELFBR,
s390x.ACELGBR,
s390x.ACDLFBR,
s390x.ACDLGBR,
s390x.ACEFBRA,
s390x.ACEGBRA,
s390x.ACDFBRA,
s390x.ACDGBRA,
s390x.AFSQRT:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
// read p->from, read p->reg, rar p->to
case s390x.ARLWMI:
if copyas(&p.To, v) {
return 2
}
fallthrough
//.........这里部分代码省略.........
作者:danny800
项目:g
//.........这里部分代码省略.........
case AMULVU:
return OP(3, 5)
case AJMP:
return OP(1, 0)
case AJAL:
return OP(1, 1)
case ABREAK:
return OP(1, 5)
case ASYSCALL:
return OP(1, 4)
case ATLBP:
return MMU(1, 0)
case ATLBR:
return MMU(0, 1)
case ATLBWI:
return MMU(0, 2)
case ATLBWR:
return MMU(0, 6)
case ARFE:
return MMU(2, 0)
case ADIVF:
return FPF(0, 3)
case ADIVD:
return FPD(0, 3)
case AMULF:
return FPF(0, 2)
case AMULD:
return FPD(0, 2)
case ASUBF:
return FPF(0, 1)
case ASUBD:
return FPD(0, 1)
case AADDF:
return FPF(0, 0)
case AADDD:
return FPD(0, 0)
case ATRUNCFV:
return FPF(1, 1)
case ATRUNCDV:
return FPD(1, 1)
case ATRUNCFW:
return FPF(1, 5)
case ATRUNCDW:
return FPD(1, 5)
case AMOVFV:
return FPF(4, 5)
case AMOVDV:
return FPD(4, 5)
case AMOVVF:
return FPV(4, 0)
case AMOVVD:
return FPV(4, 1)
case AMOVFW:
return FPF(4, 4)
case AMOVDW:
return FPD(4, 4)
case AMOVWF:
return FPW(4, 0)
case AMOVDF:
return FPD(4, 0)
case AMOVWD:
return FPW(4, 1)
case AMOVFD:
return FPF(4, 1)
case AABSF:
return FPF(0, 5)
case AABSD:
return FPD(0, 5)
case AMOVF:
return FPF(0, 6)
case AMOVD:
return FPD(0, 6)
case ANEGF:
return FPF(0, 7)
case ANEGD:
return FPD(0, 7)
case ACMPEQF:
return FPF(6, 2)
case ACMPEQD:
return FPD(6, 2)
case ACMPGTF:
return FPF(7, 4)
case ACMPGTD:
return FPD(7, 4)
case ACMPGEF:
return FPF(7, 6)
case ACMPGED:
return FPD(7, 6)
}
if a >= ALAST {
ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST))
} else {
ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
}
return 0
}
作者:ckeye
项目:gosr
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE {
// never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
mips.AMOVV,
mips.AMOVF,
mips.AMOVD,
mips.AMOVH,
mips.AMOVHU,
mips.AMOVB,
mips.AMOVBU,
mips.AMOVW,
mips.AMOVWU,
mips.AMOVFD,
mips.AMOVDF,
mips.AMOVDW,
mips.AMOVWD,
mips.AMOVFW,
mips.AMOVWF,
mips.AMOVDV,
mips.AMOVVD,
mips.AMOVFV,
mips.AMOVVF,
mips.ATRUNCFV,
mips.ATRUNCDV,
mips.ATRUNCFW,
mips.ATRUNCDW:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
case mips.ASGT, /* read p->from, read p->reg, write p->to */
mips.ASGTU,
mips.AADD,
mips.AADDU,
mips.ASUB,
mips.ASUBU,
mips.ASLL,
mips.ASRL,
mips.ASRA,
mips.AOR,
mips.ANOR,
mips.AAND,
mips.AXOR,
mips.AADDV,
mips.AADDVU,
mips.ASUBV,
//.........这里部分代码省略.........
作者:xslonepiec
项目:goio
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3.Type != obj.TYPE_NONE {
// 7g never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(&p.From3))
}
if p.To2.Type != obj.TYPE_NONE {
// 7g never generates a to2
fmt.Printf("copyu: to2 (%v) not implemented\n", gc.Ctxt.Dconv(&p.To2))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
arm64.ANEG,
arm64.AFNEGD,
arm64.AFNEGS,
arm64.AFSQRTD,
arm64.AFCVTZSD,
arm64.AFCVTZSS,
arm64.AFCVTZSDW,
arm64.AFCVTZSSW,
arm64.AFCVTZUD,
arm64.AFCVTZUS,
arm64.AFCVTZUDW,
arm64.AFCVTZUSW,
arm64.AFCVTSD,
arm64.AFCVTDS,
arm64.ASCVTFD,
arm64.ASCVTFS,
arm64.ASCVTFWD,
arm64.ASCVTFWS,
arm64.AUCVTFD,
arm64.AUCVTFS,
arm64.AUCVTFWD,
arm64.AUCVTFWS,
arm64.AMOVB,
arm64.AMOVBU,
arm64.AMOVH,
arm64.AMOVHU,
arm64.AMOVW,
arm64.AMOVWU,
arm64.AMOVD,
arm64.AFMOVS,
arm64.AFMOVD:
if p.Scond == 0 {
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
}
/* rar p->from, write p->to or read p->from, rar p->to */
if p.From.Type == obj.TYPE_MEM {
if copyas(&p.From, v) {
// No s!=nil check; need to fail
//.........这里部分代码省略.........
作者:duhaibo040
项目:go-
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE {
// 9g never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(p.As))
return 2
case obj.ANOP, /* read p->from, write p->to */
ppc64.AMOVH,
ppc64.AMOVHZ,
ppc64.AMOVB,
ppc64.AMOVBZ,
ppc64.AMOVW,
ppc64.AMOVWZ,
ppc64.AMOVD,
ppc64.ANEG,
ppc64.ANEGCC,
ppc64.AADDME,
ppc64.AADDMECC,
ppc64.AADDZE,
ppc64.AADDZECC,
ppc64.ASUBME,
ppc64.ASUBMECC,
ppc64.ASUBZE,
ppc64.ASUBZECC,
ppc64.AFCTIW,
ppc64.AFCTIWZ,
ppc64.AFCTID,
ppc64.AFCTIDZ,
ppc64.AFCFID,
ppc64.AFCFIDCC,
ppc64.AFMOVS,
ppc64.AFMOVD,
ppc64.AFRSP,
ppc64.AFNEG,
ppc64.AFNEGCC,
ppc64.AFSQRT:
if s != nil {
if copysub(&p.From, v, s, true) {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, true) {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
case ppc64.AMOVBU, /* rar p->from, write p->to or read p->from, rar p->to */
ppc64.AMOVBZU,
ppc64.AMOVHU,
ppc64.AMOVHZU,
ppc64.AMOVWZU,
ppc64.AMOVDU:
if p.From.Type == obj.TYPE_MEM {
if copyas(&p.From, v) {
// No s!=nil check; need to fail
// anyway in that case
return 2
}
//.........这里部分代码省略.........
作者:duhaibo040
项目:go-
//.........这里部分代码省略.........
}
}
}
}
if t != 0 {
goto loop1
}
/*
* look for MOVB x,R; MOVB R,R (for small MOVs not handled above)
*/
var p1 *obj.Prog
var r1 *gc.Flow
for r := g.Start; r != nil; r = r.Link {
p = r.Prog
switch p.As {
default:
continue
case arm64.AMOVH,
arm64.AMOVHU,
arm64.AMOVB,
arm64.AMOVBU,
arm64.AMOVW,
arm64.AMOVWU:
if p.To.Type != obj.TYPE_REG {
continue
}
}
r1 = r.Link
if r1 == nil {
continue
}
p1 = r1.Prog
if p1.As != p.As {
continue
}
if p1.From.Type != obj.TYPE_REG || p1.From.Reg != p.To.Reg {
continue
}
if p1.To.Type != obj.TYPE_REG || p1.To.Reg != p.To.Reg {
continue
}
excise(r1)
}
if gc.Debug['D'] > 1 {
goto ret /* allow following code improvement to be suppressed */
}
// MOVD $c, R'; ADD R', R (R' unused) -> ADD $c, R
for r := g.Start; r != nil; r = r.Link {
p = r.Prog
switch p.As {
default:
continue
case arm64.AMOVD:
if p.To.Type != obj.TYPE_REG {
continue
}
if p.From.Type != obj.TYPE_CONST {
continue
}
if p.From.Offset < 0 || 4096 <= p.From.Offset {
continue
}
}
r1 = r.Link
if r1 == nil {
continue
}
p1 = r1.Prog
if p1.As != arm64.AADD && p1.As != arm64.ASUB { // TODO(aram): also logical after we have bimm.
continue
}
if p1.From.Type != obj.TYPE_REG || p1.From.Reg != p.To.Reg {
continue
}
if p1.To.Type != obj.TYPE_REG {
continue
}
if gc.Debug['P'] != 0 {
fmt.Printf("encoding $%d directly into %v in:\n%v\n%v\n", p.From.Offset, obj.Aconv(p1.As), p, p1)
}
p1.From.Type = obj.TYPE_CONST
p1.From = p.From
excise(r)
}
/* TODO(minux):
* look for OP x,y,R; CMP R, $0 -> OP.S x,y,R
* when OP can set condition codes correctly
*/
ret:
gc.Flowend(g)
}
作者:danny800
项目:g
//.........这里部分代码省略.........
case ABGTZ:
return SP(0, 7)
case ABGTZ + ALAST:
return SP(2, 7) /* likely */
case ABLEZ:
return SP(0, 6)
case ABLEZ + ALAST:
return SP(2, 6) /* likely */
case ABLTZ:
return SP(0, 1) | BCOND(0, 0)
case ABLTZ + ALAST:
return SP(0, 1) | BCOND(0, 2) /* likely */
case ABLTZAL:
return SP(0, 1) | BCOND(2, 0)
case ABLTZAL + ALAST:
return SP(0, 1) | BCOND(2, 2) /* likely */
case ABFPT:
return SP(2, 1) | (257 << 16)
case ABFPT + ALAST:
return SP(2, 1) | (259 << 16) /* likely */
case ABFPF:
return SP(2, 1) | (256 << 16)
case ABFPF + ALAST:
return SP(2, 1) | (258 << 16) /* likely */
case AMOVB,
AMOVBU:
return SP(5, 0)
case AMOVH,
AMOVHU:
return SP(5, 1)
case AMOVW,
AMOVWU:
return SP(5, 3)
case AMOVV:
return SP(7, 7)
case AMOVF:
return SP(7, 1)
case AMOVD:
return SP(7, 5)
case AMOVWL:
return SP(5, 2)
case AMOVWR:
return SP(5, 6)
case AMOVVL:
return SP(5, 4)
case AMOVVR:
return SP(5, 5)
case ABREAK:
return SP(5, 7)
case AMOVWL + ALAST:
return SP(4, 2)
case AMOVWR + ALAST:
return SP(4, 6)
case AMOVVL + ALAST:
return SP(3, 2)
case AMOVVR + ALAST:
return SP(3, 3)
case AMOVB + ALAST:
return SP(4, 0)
case AMOVBU + ALAST:
return SP(4, 4)
case AMOVH + ALAST:
return SP(4, 1)
case AMOVHU + ALAST:
return SP(4, 5)
case AMOVW + ALAST:
return SP(4, 3)
case AMOVWU + ALAST:
return SP(4, 7)
case AMOVV + ALAST:
return SP(6, 7)
case AMOVF + ALAST:
return SP(6, 1)
case AMOVD + ALAST:
return SP(6, 5)
case ASLLV:
return OP(7, 0)
case ASRLV:
return OP(7, 2)
case ASRAV:
return OP(7, 3)
case ASLLV + ALAST:
return OP(7, 4)
case ASRLV + ALAST:
return OP(7, 6)
case ASRAV + ALAST:
return OP(7, 7)
}
if a >= ALAST {
ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST))
} else {
ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
}
return 0
}
作者:xiezerozer
项目:g
/*
* return
* 1 if v only used (and substitute),
* 2 if read-alter-rewrite
* 3 if set
* 4 if set and used
* 0 otherwise (not touched)
*/
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case arm.AMOVM:
if v.Type != obj.TYPE_REG {
return 0
}
if p.From.Type == obj.TYPE_CONST { /* read reglist, read/rar */
if s != nil {
if p.From.Offset&(1<<uint(v.Reg)) != 0 {
return 1
}
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
return 0
}
if copyau(&p.To, v) {
if p.Scond&arm.C_WBIT != 0 {
return 2
}
return 1
}
if p.From.Offset&(1<<uint(v.Reg)) != 0 {
return 1 /* read/rar, write reglist */
}
} else {
if s != nil {
if p.To.Offset&(1<<uint(v.Reg)) != 0 {
return 1
}
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
return 0
}
if copyau(&p.From, v) {
if p.Scond&arm.C_WBIT != 0 {
return 2
}
if p.To.Offset&(1<<uint(v.Reg)) != 0 {
return 4
}
return 1
}
if p.To.Offset&(1<<uint(v.Reg)) != 0 {
return 3
}
}
return 0
case obj.ANOP, /* read,, write */
arm.ASQRTD,
arm.AMOVW,
arm.AMOVF,
arm.AMOVD,
arm.AMOVH,
arm.AMOVHS,
arm.AMOVHU,
arm.AMOVB,
arm.AMOVBS,
arm.AMOVBU,
arm.AMOVFW,
arm.AMOVWF,
arm.AMOVDW,
arm.AMOVWD,
arm.AMOVFD,
arm.AMOVDF:
if p.Scond&(arm.C_WBIT|arm.C_PBIT) != 0 {
if v.Type == obj.TYPE_REG {
if p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_SHIFT {
if p.From.Reg == v.Reg {
return 2
}
} else {
if p.To.Reg == v.Reg {
return 2
}
}
}
}
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
//.........这里部分代码省略.........
作者:danny800
项目:g
func buildop(ctxt *obj.Link) {
var n int
for i := 0; i < C_NCLASS; i++ {
for n = 0; n < C_NCLASS; n++ {
if cmp(n, i) {
xcmp[i][n] = 1
}
}
}
for n = 0; optab[n].as != obj.AXXX; n++ {
}
sort.Sort(ocmp(optab[:n]))
for i := 0; i < n; i++ {
r := optab[i].as
r0 := r & obj.AMask
oprange[r0].start = optab[i:]
for optab[i].as == r {
i++
}
oprange[r0].stop = optab[i:]
i--
switch r {
default:
ctxt.Diag("unknown op in build: %v", obj.Aconv(int(r)))
log.Fatalf("bad code")
case AABSF:
opset(AMOVFD, r0)
opset(AMOVDF, r0)
opset(AMOVWF, r0)
opset(AMOVFW, r0)
opset(AMOVWD, r0)
opset(AMOVDW, r0)
opset(ANEGF, r0)
opset(ANEGD, r0)
opset(AABSD, r0)
opset(ATRUNCDW, r0)
opset(ATRUNCFW, r0)
opset(ATRUNCDV, r0)
opset(ATRUNCFV, r0)
opset(AMOVVF, r0)
opset(AMOVFV, r0)
opset(AMOVVD, r0)
opset(AMOVDV, r0)
case AADD:
opset(ASGT, r0)
opset(ASGTU, r0)
opset(AADDU, r0)
opset(AADDV, r0)
opset(AADDVU, r0)
case AADDF:
opset(ADIVF, r0)
opset(ADIVD, r0)
opset(AMULF, r0)
opset(AMULD, r0)
opset(ASUBF, r0)
opset(ASUBD, r0)
opset(AADDD, r0)
case AAND:
opset(AOR, r0)
opset(AXOR, r0)
case ABEQ:
opset(ABNE, r0)
case ABLEZ:
opset(ABGEZ, r0)
opset(ABGEZAL, r0)
opset(ABLTZ, r0)
opset(ABLTZAL, r0)
opset(ABGTZ, r0)
case AMOVB:
opset(AMOVH, r0)
case AMOVBU:
opset(AMOVHU, r0)
case AMUL:
opset(AREM, r0)
opset(AREMU, r0)
opset(ADIVU, r0)
opset(AMULU, r0)
opset(ADIV, r0)
opset(ADIVV, r0)
opset(ADIVVU, r0)
opset(AMULV, r0)
opset(AMULVU, r0)
opset(AREMV, r0)
opset(AREMVU, r0)
case ASLL:
opset(ASRL, r0)
opset(ASRA, r0)
opset(ASLLV, r0)
//.........这里部分代码省略.........