We currently use two fields to store the targets of branches.
Some phases use p.To.Val, some use p.Pcond. Rewrite so that
every branch instruction uses p.To.Val.
p.From.Val is also used in rare instances.
Introduce a Pool link for use by arm/arm64, instead of
repurposing Pcond.
This is a cleanup CL in preparation for some stack frame CLs.
Change-Id: If8239177e4b1ea2bccd0608eb39553d23210d405
Reviewed-on: https://go-review.googlesource.com/c/go/+/251437
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
// TODO(khr): issue only the -1 fixup code we need.
// For instance, if only the quotient is used, no point in zeroing the remainder.
- j1.To.Val = n1
- j2.To.Val = s.Pc()
+ j1.To.SetTarget(n1)
+ j2.To.SetTarget(s.Pc())
}
case ssa.OpAMD64HMULQ, ssa.OpAMD64HMULL, ssa.OpAMD64HMULQU, ssa.OpAMD64HMULLU:
if p.To.Type != obj.TYPE_BRANCH {
Fatalf("patch: not a branch")
}
- p.To.Val = to
+ p.To.SetTarget(to)
p.To.Offset = to.Pc
}
// Resolve branches, and relax DefaultStmt into NotStmt
for _, br := range s.Branches {
- br.P.To.Val = s.bstart[br.B.ID]
+ br.P.To.SetTarget(s.bstart[br.B.ID])
if br.P.Pos.IsStmt() != src.PosIsStmt {
br.P.Pos = br.P.Pos.WithNotStmt()
} else if v0 := br.B.FirstPossibleStmtValue(); v0 != nil && v0.Pos.Line() == br.P.Pos.Line() && v0.Pos.IsStmt() == src.PosIsStmt {
n.To.Reg = dividend
}
- j.To.Val = n
- j2.To.Val = s.Pc()
+ j.To.SetTarget(n)
+ j2.To.SetTarget(s.Pc())
}
case ssa.OpS390XADDconst, ssa.OpS390XADDWconst:
opregregimm(s, v.Op.Asm(), v.Reg(), v.Args[0].Reg(), v.AuxInt)
n.To.Reg = x86.REG_DX
}
- j.To.Val = n
- j2.To.Val = s.Pc()
+ j.To.SetTarget(n)
+ j2.To.SetTarget(s.Pc())
}
case ssa.Op386HMULL, ssa.Op386HMULLU:
q := c.newprog()
q.As = AB
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = p.Link
+ q.To.SetTarget(p.Link)
q.Link = c.blitrl
q.Pos = p.Pos
c.blitrl = q
if t.Rel == nil {
for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
if q.Rel == nil && q.To == t.To {
- p.Pcond = q
+ p.Pool = q
return
}
}
c.elitrl = q
c.pool.size += 4
- // Store the link to the pool entry in Pcond.
- p.Pcond = q
+ // Store the link to the pool entry in Pool.
+ p.Pool = q
}
func (c *ctxt5) regoff(a *obj.Addr) int32 {
break
}
- if p.Pcond != nil {
- v = int32((p.Pcond.Pc - c.pc) - 8)
+ if p.To.Target() != nil {
+ v = int32((p.To.Target().Pc - c.pc) - 8)
}
o1 |= (uint32(v) >> 2) & 0xffffff
func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
var o1 uint32
- if p.Pcond == nil {
+ if p.Pool == nil {
c.aclass(a)
v := immrot(^uint32(c.instoffset))
if v == 0 {
o1 |= uint32(v)
o1 |= (uint32(dr) & 15) << 12
} else {
- v := int32(p.Pcond.Pc - p.Pc - 8)
+ v := int32(p.Pool.Pc - p.Pc - 8)
o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
}
mov.To.Reg = REG_R2
// B.NE branch target is MOVW above
- bne.Pcond = mov
+ bne.To.SetTarget(mov)
// ADD $(autosize+4), R13, R3
p = obj.Appendp(mov, newprog)
p = obj.Appendp(p, newprog)
p.As = ABNE
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = end
+ p.To.SetTarget(end)
// ADD $4, R13, R4
p = obj.Appendp(p, newprog)
p = obj.Appendp(p, newprog)
p.As = AB
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = end
+ p.To.SetTarget(end)
// reset for subsequent passes
p = end
movw.To.Type = obj.TYPE_REG
movw.To.Reg = REG_R3
- bls.Pcond = movw
+ bls.To.SetTarget(movw)
// BL runtime.morestack
call := obj.Appendp(movw, c.newprog)
b := obj.Appendp(pcdata, c.newprog)
b.As = obj.AJMP
b.To.Type = obj.TYPE_BRANCH
- b.Pcond = c.cursym.Func.Text.Link
+ b.To.SetTarget(c.cursym.Func.Text.Link)
b.Spadj = +framesize
return end
o = c.oplook(p)
/* very large branches */
- if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
- otxt := p.Pcond.Pc - pc
+ if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.To.Target() != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
+ otxt := p.To.Target().Pc - pc
var toofar bool
switch o.type_ {
case 7, 39: // branch instruction encodes 19 bits
p.Link = q
q.As = AB
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = p.Pcond
- p.Pcond = q
+ q.To.SetTarget(p.To.Target())
+ p.To.SetTarget(q)
q = c.newprog()
q.Link = p.Link
p.Link = q
q.As = AB
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = q.Link.Link
+ q.To.SetTarget(q.Link.Link)
bflag = 1
}
}
q := c.newprog()
q.As = AB
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = p.Link
+ q.To.SetTarget(p.Link)
q.Link = c.blitrl
q.Pos = p.Pos
c.blitrl = q
for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
if q.To == t.To {
- p.Pcond = q
+ p.Pool = q
return
}
}
c.elitrl = q
c.pool.size = -c.pool.size & (funcAlign - 1)
c.pool.size += uint32(sz)
- p.Pcond = q
+ p.Pool = q
}
func (c *ctxt7) regoff(a *obj.Addr) uint32 {
func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
v := int64(0)
t := int64(0)
- if p.Pcond != nil {
- v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
+ q := p.To.Target()
+ if q == nil {
+ // TODO: don't use brdist for this case, as it isn't a branch.
+ // (Calls from omovlit, and maybe adr/adrp opcodes as well.)
+ q = p.Pool
+ }
+ if q != nil {
+ v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
if (v & ((1 << uint(shift)) - 1)) != 0 {
c.ctxt.Diag("misaligned label\n%v", p)
}
v >>= uint(shift)
t = int64(1) << uint(flen-1)
if v < -t || v >= t {
- c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond)
+ c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
panic("branch too far")
}
}
*/
func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
var o1 int32
- if p.Pcond == nil { /* not in literal pool */
+ if p.Pool == nil { /* not in literal pool */
c.aclass(a)
c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
w = 1 /* 64-bit SIMD/FP */
case AMOVD:
- if p.Pcond.As == ADWORD {
+ if p.Pool.As == ADWORD {
w = 1 /* 64-bit */
- } else if p.Pcond.To.Offset < 0 {
+ } else if p.Pool.To.Offset < 0 {
w = 2 /* 32-bit, sign-extended to 64-bit */
- } else if p.Pcond.To.Offset >= 0 {
+ } else if p.Pool.To.Offset >= 0 {
w = 0 /* 32-bit, zero-extended to 64-bit */
} else {
c.ctxt.Diag("invalid operand %v in %v", a, p)
movlr.To.Type = obj.TYPE_REG
movlr.To.Reg = REG_R3
if q != nil {
- q.Pcond = movlr
+ q.To.SetTarget(movlr)
}
- bls.Pcond = movlr
+ bls.To.SetTarget(movlr)
debug := movlr
if false {
jmp := obj.Appendp(pcdata, c.newprog)
jmp.As = AB
jmp.To.Type = obj.TYPE_BRANCH
- jmp.Pcond = c.cursym.Func.Text.Link
+ jmp.To.SetTarget(c.cursym.Func.Text.Link)
jmp.Spadj = +framesize
return end
mov.To.Reg = REG_R2
// CBNZ branches to the MOV above
- cbnz.Pcond = mov
+ cbnz.To.SetTarget(mov)
// ADD $(autosize+8), SP, R3
q = obj.Appendp(mov, c.newprog)
q = obj.Appendp(q, c.newprog)
q.As = ABNE
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = end
+ q.To.SetTarget(end)
// ADD $8, SP, R4
q = obj.Appendp(q, c.newprog)
q = obj.Appendp(q, c.newprog)
q.As = AB
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = end
+ q.To.SetTarget(end)
}
case obj.ARET:
q5.Reg = REGSP
q5.To.Type = obj.TYPE_REG
q5.To.Reg = REGFP
- q1.Pcond = q5
+ q1.From.SetTarget(q5)
p = q5
}
q5.Reg = REGSP
q5.To.Type = obj.TYPE_REG
q5.To.Reg = REGFP
- q1.Pcond = q5
+ q1.From.SetTarget(q5)
p = q5
}
}
TYPE_REGLIST
)
+func (a *Addr) Target() *Prog {
+ if a.Type == TYPE_BRANCH && a.Val != nil {
+ return a.Val.(*Prog)
+ }
+ return nil
+}
+func (a *Addr) SetTarget(t *Prog) {
+ if a.Type != TYPE_BRANCH {
+ panic("setting branch target when type is not TYPE_BRANCH")
+ }
+ a.Val = t
+}
+
// Prog describes a single machine instruction.
//
// The general instruction form is:
// to avoid too much changes in a single swing.
// (1) scheme is enough to express any kind of operand combination.
//
-// Jump instructions use the Pcond field to point to the target instruction,
+// Jump instructions use the To.Val field to point to the target *Prog,
// which must be in the same linked list as the jump instruction.
//
// The Progs for a given function are arranged in a list linked through the Link field.
From Addr // first source operand
RestArgs []Addr // can pack any operands that not fit into {Prog.From, Prog.To}
To Addr // destination operand (second is RegTo2 below)
- Pcond *Prog // target of conditional jump
+ Pool *Prog // constant pool entry, for arm,arm64 back ends
Forwd *Prog // for x86 back end
Rel *Prog // for x86, arm back ends
Pc int64 // for back ends or assembler: virtual or actual program counter, depending on phase
o = c.oplook(p)
// very large conditional branches
- if o.type_ == 6 && p.Pcond != nil {
- otxt = p.Pcond.Pc - pc
+ if o.type_ == 6 && p.To.Target() != nil {
+ otxt = p.To.Target().Pc - pc
if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
q = c.newprog()
q.Link = p.Link
q.As = AJMP
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = p.Pcond
- p.Pcond = q
+ q.To.SetTarget(p.To.Target())
+ p.To.SetTarget(q)
q = c.newprog()
q.Link = p.Link
p.Link = q
q.As = AJMP
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = q.Link.Link
+ q.To.SetTarget(q.Link.Link)
c.addnop(p.Link)
c.addnop(p)
case 6: /* beq r1,[r2],sbra */
v := int32(0)
- if p.Pcond == nil {
+ if p.To.Target() == nil {
v = int32(-4) >> 2
} else {
- v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+ v = int32(p.To.Target().Pc-p.Pc-4) >> 2
}
if (v<<16)>>16 != v {
c.ctxt.Diag("short branch too far\n%v", p)
if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
// use PC-relative branch for short branches
// BEQ R0, R0, sbra
- if p.Pcond == nil {
+ if p.To.Target() == nil {
v = int32(-4) >> 2
} else {
- v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+ v = int32(p.To.Target().Pc-p.Pc-4) >> 2
}
if (v<<16)>>16 == v {
o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
break
}
}
- if p.Pcond == nil {
+ if p.To.Target() == nil {
v = int32(p.Pc) >> 2
} else {
- v = int32(p.Pcond.Pc) >> 2
+ v = int32(p.To.Target().Pc) >> 2
}
o1 = OP_JMP(c.opirr(p.As), uint32(v))
if p.To.Sym == nil {
p.To.Sym = c.cursym.Func.Text.From.Sym
- p.To.Offset = p.Pcond.Pc
+ p.To.Offset = p.To.Target().Pc
}
rel := obj.Addrel(c.cursym)
rel.Off = int32(c.pc)
} else {
p.Mark |= BRANCH
}
- q1 := p.Pcond
+ q1 := p.To.Target()
if q1 != nil {
for q1.As == obj.ANOP {
q1 = q1.Link
- p.Pcond = q1
+ p.To.SetTarget(q1)
}
if q1.Mark&LEAF == 0 {
q = obj.Appendp(q, newprog)
q.As = obj.ANOP
- p1.Pcond = q
- p2.Pcond = q
+ p1.To.SetTarget(q)
+ p2.To.SetTarget(q)
}
case ARET:
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R3
if q != nil {
- q.Pcond = p
+ q.To.SetTarget(p)
p.Mark |= LABEL
}
p.As = AJMP
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = c.cursym.Func.Text.Link
+ p.To.SetTarget(c.cursym.Func.Text.Link)
p.Mark |= BRANCH
// placeholder for q1's jump target
p = obj.Appendp(p, c.newprog)
p.As = obj.ANOP // zero-width place holder
- q1.Pcond = p
+ q1.To.SetTarget(p)
return p
}
// In the case of an infinite loop, brloop returns nil.
func brloop(p *Prog) *Prog {
c := 0
- for q := p; q != nil; q = q.Pcond {
- if q.As != AJMP || q.Pcond == nil {
+ for q := p; q != nil; q = q.To.Target() {
+ if q.As != AJMP || q.To.Target() == nil {
return q
}
c++
continue
}
if p.To.Val != nil {
- // TODO: Remove To.Val.(*Prog) in favor of p->pcond.
- p.Pcond = p.To.Val.(*Prog)
continue
}
p.To.Type = TYPE_NONE
}
- p.To.Val = q
- p.Pcond = q
+ p.To.SetTarget(q)
}
if !ctxt.Flag_optimize {
// Collapse series of jumps to jumps.
for p := sym.Func.Text; p != nil; p = p.Link {
- if p.Pcond == nil {
+ if p.To.Target() == nil {
continue
}
- p.Pcond = brloop(p.Pcond)
- if p.Pcond != nil && p.To.Type == TYPE_BRANCH {
- p.To.Offset = p.Pcond.Pc
+ p.To.SetTarget(brloop(p.To.Target()))
+ if p.To.Target() != nil && p.To.Type == TYPE_BRANCH {
+ p.To.Offset = p.To.Target().Pc
}
}
}
o = c.oplook(p)
// very large conditional branches
- if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
- otxt = p.Pcond.Pc - pc
+ if (o.type_ == 16 || o.type_ == 17) && p.To.Target() != nil {
+ otxt = p.To.Target().Pc - pc
if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
q = c.newprog()
q.Link = p.Link
p.Link = q
q.As = ABR
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = p.Pcond
- p.Pcond = q
+ q.To.SetTarget(p.To.Target())
+ p.To.SetTarget(q)
q = c.newprog()
q.Link = p.Link
p.Link = q
q.As = ABR
q.To.Type = obj.TYPE_BRANCH
- q.Pcond = q.Link.Link
+ q.To.SetTarget(q.Link.Link)
//addnop(p->link);
//addnop(p);
case 11: /* br/bl lbra */
v := int32(0)
- if p.Pcond != nil {
- v = int32(p.Pcond.Pc - p.Pc)
+ if p.To.Target() != nil {
+ v = int32(p.To.Target().Pc - p.Pc)
if v&03 != 0 {
c.ctxt.Diag("odd branch target address\n%v", p)
v &^= 03
}
}
v := int32(0)
- if p.Pcond != nil {
- v = int32(p.Pcond.Pc - p.Pc)
+ if p.To.Target() != nil {
+ v = int32(p.To.Target().Pc - p.Pc)
}
if v&03 != 0 {
c.ctxt.Diag("odd branch target address\n%v", p)
ABVS:
p.Mark |= BRANCH
q = p
- q1 = p.Pcond
+ q1 = p.To.Target()
if q1 != nil {
// NOPs are not removed due to #40689.
q = obj.Appendp(q, c.newprog)
q.As = obj.ANOP
- p1.Pcond = q
- p2.Pcond = q
+ p1.To.SetTarget(q)
+ p2.To.SetTarget(q)
}
case obj.ARET:
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R5
if q != nil {
- q.Pcond = p
+ q.To.SetTarget(p)
}
p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
p = obj.Appendp(p, c.newprog)
p.As = ABR
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = p0.Link
+ p.To.SetTarget(p0.Link)
// placeholder for q1's jump target
p = obj.Appendp(p, c.newprog)
p.As = obj.ANOP // zero-width place holder
- q1.Pcond = p
+ q1.To.SetTarget(p)
return p
}
getargp.Reg = 0
getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
- bneadj.Pcond = getargp
+ bneadj.To.SetTarget(getargp)
calcargp := obj.Appendp(getargp, newprog)
calcargp.As = AADDI
testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12}
testargp.Reg = REG_X13
testargp.To.Type = obj.TYPE_BRANCH
- testargp.Pcond = endadj
+ testargp.To.SetTarget(endadj)
adjargp := obj.Appendp(testargp, newprog)
adjargp.As = AADDI
godone.As = AJAL
godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
godone.To.Type = obj.TYPE_BRANCH
- godone.Pcond = endadj
+ godone.To.SetTarget(endadj)
}
// Update stack-based offsets.
if p.To.Type != obj.TYPE_BRANCH {
panic("assemble: instruction with branch-like opcode lacks destination")
}
- offset := p.Pcond.Pc - p.Pc
+ offset := p.To.Target().Pc - p.Pc
if offset < -4096 || 4096 <= offset {
// Branch is long. Replace it with a jump.
jmp := obj.Appendp(p, newprog)
jmp.As = AJAL
jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
- jmp.Pcond = p.Pcond
+ jmp.To.SetTarget(p.To.Target())
p.As = InvertBranch(p.As)
- p.Pcond = jmp.Link
+ p.To.SetTarget(jmp.Link)
// We may have made previous branches too long,
// so recheck them.
rescan = true
}
case AJAL:
- if p.Pcond == nil {
+ if p.To.Target() == nil {
panic("intersymbol jumps should be expressed as AUIPC+JALR")
}
- offset := p.Pcond.Pc - p.Pc
+ offset := p.To.Target().Pc - p.Pc
if offset < -(1<<20) || (1<<20) <= offset {
// Replace with 2-instruction sequence. This assumes
// that TMP is not live across J instructions, since
// fixed up in the next loop.
p.As = AAUIPC
p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
+ p.From.SetTarget(p.To.Target())
p.Reg = 0
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, AJAL:
switch p.To.Type {
case obj.TYPE_BRANCH:
- p.To.Type, p.To.Offset = obj.TYPE_CONST, p.Pcond.Pc-p.Pc
+ p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
case obj.TYPE_MEM:
panic("unhandled type")
}
case AAUIPC:
if p.From.Type == obj.TYPE_BRANCH {
- low, high, err := Split32BitImmediate(p.Pcond.Pc - p.Pc)
+ low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
if err != nil {
- ctxt.Diag("%v: jump displacement %d too large", p, p.Pcond.Pc-p.Pc)
+ ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
}
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
p.Link.From.Offset = low
p.To.Sym = ctxt.Lookup("runtime.morestack")
}
if to_more != nil {
- to_more.Pcond = p
+ to_more.To.SetTarget(p)
}
p = jalrToSym(ctxt, p, newprog, REG_X5)
p.As = AJAL
p.To = obj.Addr{Type: obj.TYPE_BRANCH}
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
- p.Pcond = cursym.Func.Text.Link
+ p.To.SetTarget(cursym.Func.Text.Link)
// placeholder for to_done's jump target
p = obj.Appendp(p, newprog)
p.As = obj.ANOP // zero-width place holder
- to_done.Pcond = p
+ to_done.To.SetTarget(p)
return p
}
case 11: // br/bl
v := int32(0)
- if p.Pcond != nil {
- v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ if p.To.Target() != nil {
+ v = int32((p.To.Target().Pc - p.Pc) >> 1)
}
if p.As == ABR && p.To.Sym == nil && int32(int16(v)) == v {
case 16: // conditional branch
v := int32(0)
- if p.Pcond != nil {
- v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ if p.To.Target() != nil {
+ v = int32((p.To.Target().Pc - p.Pc) >> 1)
}
mask := uint32(c.branchMask(p))
if p.To.Sym == nil && int32(int16(v)) == v {
case 41: // branch on count
r1 := p.From.Reg
- ri2 := (p.Pcond.Pc - p.Pc) >> 1
+ ri2 := (p.To.Target().Pc - p.Pc) >> 1
if int64(int16(ri2)) != ri2 {
c.ctxt.Diag("branch target too far away")
}
case 89: // compare and branch reg reg
var v int32
- if p.Pcond != nil {
- v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ if p.To.Target() != nil {
+ v = int32((p.To.Target().Pc - p.Pc) >> 1)
}
// Some instructions take a mask as the first argument.
case 90: // compare and branch reg $constant
var v int32
- if p.Pcond != nil {
- v = int32((p.Pcond.Pc - p.Pc) >> 1)
+ if p.To.Target() != nil {
+ v = int32((p.To.Target().Pc - p.Pc) >> 1)
}
// Some instructions take a mask as the first argument.
q = obj.Appendp(q, c.newprog)
q.As = obj.ANOP
- p1.Pcond = q
- p2.Pcond = q
+ p1.To.SetTarget(q)
+ p2.To.SetTarget(q)
}
case obj.ARET:
// MOVD LR, R5
p = obj.Appendp(pcdata, c.newprog)
- pPre.Pcond = p
+ pPre.To.SetTarget(p)
p.As = AMOVD
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_LR
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R5
if pPreempt != nil {
- pPreempt.Pcond = p
+ pPreempt.To.SetTarget(p)
}
// BL runtime.morestack(SB)
p.As = ABR
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = c.cursym.Func.Text.Link
+ p.To.SetTarget(c.cursym.Func.Text.Link)
return p
}
case TYPE_BRANCH:
if a.Sym != nil {
fmt.Fprintf(w, "%s(SB)", a.Sym.Name)
- } else if p != nil && p.Pcond != nil {
- fmt.Fprint(w, p.Pcond.Pc)
- } else if a.Val != nil {
- fmt.Fprint(w, a.Val.(*Prog).Pc)
+ } else if a.Target() != nil {
+ fmt.Fprint(w, a.Target().Pc)
} else {
fmt.Fprintf(w, "%d(PC)", a.Offset)
}
// no standalone or macro-fused jump will straddle or end on a 32 byte boundary
// by inserting NOPs before the jumps
func isJump(p *obj.Prog) bool {
- return p.Pcond != nil || p.As == obj.AJMP || p.As == obj.ACALL ||
+ return p.To.Target() != nil || p.As == obj.AJMP || p.As == obj.ACALL ||
p.As == obj.ARET || p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO
}
for q = p.Link; q != nil && (q.As == obj.APCDATA || q.As == obj.AFUNCDATA || q.As == obj.ANOP); q = q.Link {
}
- if q == nil || q.Pcond == nil || p.As == obj.AJMP || p.As == obj.ACALL {
+ if q == nil || q.To.Target() == nil || p.As == obj.AJMP || p.As == obj.ACALL {
return nil
}
}
for p := s.Func.Text; p != nil; p = p.Link {
- if p.To.Type == obj.TYPE_BRANCH && p.Pcond == nil {
- p.Pcond = p
+ if p.To.Type == obj.TYPE_BRANCH && p.To.Target() == nil {
+ p.To.SetTarget(p)
}
if p.As == AADJSP {
p.To.Type = obj.TYPE_REG
for p := s.Func.Text; p != nil; p = p.Link {
count++
p.Back = branchShort // use short branches first time through
- if q := p.Pcond; q != nil && (q.Back&branchShort != 0) {
+ if q := p.To.Target(); q != nil && (q.Back&branchShort != 0) {
p.Back |= branchBackwards
q.Back |= branchLoopHead
}
// TODO: Check in input, preserve in brchain.
// Fill in backward jump now.
- q = p.Pcond
+ q = p.To.Target()
if q == nil {
ctxt.Diag("jmp/branch/loop without target")
}
// Set jne branch target.
- jne.Pcond = p
+ jne.To.SetTarget(p)
// CMPQ panic_argp(BX), DI
p = obj.Appendp(p, newprog)
p = obj.Appendp(p, newprog)
p.As = AJNE
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = end
+ p.To.SetTarget(end)
// MOVQ SP, panic_argp(BX)
p = obj.Appendp(p, newprog)
p = obj.Appendp(p, newprog)
p.As = obj.AJMP
p.To.Type = obj.TYPE_BRANCH
- p.Pcond = end
+ p.To.SetTarget(end)
// Reset p for following code.
p = end
jmp := obj.Appendp(pcdata, newprog)
jmp.As = obj.AJMP
jmp.To.Type = obj.TYPE_BRANCH
- jmp.Pcond = cursym.Func.Text.Link
+ jmp.To.SetTarget(cursym.Func.Text.Link)
jmp.Spadj = +framesize
- jls.Pcond = call
+ jls.To.SetTarget(call)
if q1 != nil {
- q1.Pcond = call
+ q1.To.SetTarget(call)
}
return end