It shrinks Prog type from 448 bytes down to 376 bytes on amd64.
It also makes sense, because I don't know of any modern architecture
that have instructions which can write to two destinations, none of
which is a register (even x86 doesn't have such instructions).
Change-Id: I3061f1c9ac93d79ee2b92ecb9049641d0e0f6300
Reviewed-on: https://go-review.googlesource.com/10330
Reviewed-by: Aram Hăvărneanu <aram@mgk.ro>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
if arch.IsARM64STLXR(op) {
prog.From = a[0]
prog.To = a[1]
- prog.To2 = a[2]
+ if a[2].Type != obj.TYPE_REG {
+ p.errorf("invalid addressing modes for third operand to %s instruction, must be register", obj.Aconv(op))
+ }
+ prog.RegTo2 = a[2].Reg
break
}
prog.From = a[0]
// 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 {
+ if p.RegTo2 != obj.REG_NONE {
// 7g never generates a to2
- fmt.Printf("copyu: to2 (%v) not implemented\n", gc.Ctxt.Dconv(&p.To2))
+ fmt.Printf("copyu: RegTo2 (%v) not implemented\n", obj.Rconv(int(p.RegTo2)))
}
switch p.As {
case 59: /* stxr/stlxr */
o1 = opstore(ctxt, int(p.As))
- if p.To2.Type != obj.TYPE_NONE {
- o1 |= uint32(p.To2.Reg&31) << 16
+ if p.RegTo2 != obj.REG_NONE {
+ o1 |= uint32(p.RegTo2&31) << 16
} else {
o1 |= 0x1F << 16
}
From Addr
From3 Addr
To Addr
- To2 Addr
Opt interface{}
Forwd *Prog
Pcond *Prog
Spadj int32
As int16
Reg int16
+ RegTo2 int16 // 2nd register output operand
Mark uint16
Optab uint16
Scond uint8
if p.To.Type != TYPE_NONE {
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To))
}
- if p.To2.Type != TYPE_NONE {
- fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To2))
+ if p.RegTo2 != REG_NONE {
+ fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.RegTo2)))
}
return buf.String()
}
if p.From3.Name == obj.NAME_EXTERN {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
- if p.To2.Name == obj.NAME_EXTERN {
- ctxt.Diag("don't know how to handle %v with -dynlink", p)
- }
var source *obj.Addr
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {