const (
// Optab.flag
LFROM = 1 << iota // p.From uses constant pool
- LFROM128 // p.From3<<64+p.From forms a 128-bit constant in literal pool
LTO // p.To uses constant pool
NOTUSETMP // p expands to multiple instructions, but does NOT use REGTMP
BRANCH14BITS // branch instruction encodes 14 bits
/* load long effective stack address (load int32 offset and add) */
{AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, C_NONE, 34, 8, REGSP, LFROM, 0},
- // Move a large constant to a vector register.
- {AVMOVQ, C_VCON, C_NONE, C_VCON, C_VREG, C_NONE, 101, 4, 0, LFROM128, 0},
- {AVMOVD, C_VCON, C_NONE, C_NONE, C_VREG, C_NONE, 101, 4, 0, LFROM, 0},
- {AVMOVS, C_LCON, C_NONE, C_NONE, C_VREG, C_NONE, 101, 4, 0, LFROM, 0},
+ // Load a large constant into a vector register.
+ {AVMOVS, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
+ {AVMOVD, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
+ {AVMOVQ, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
/* jump operations */
{AB, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0},
if o.flag&LFROM != 0 {
c.addpool(p, &p.From)
}
- if o.flag&LFROM128 != 0 {
- c.addpool128(p, &p.From, p.GetFrom3())
- }
if o.flag<O != 0 {
c.addpool(p, &p.To)
}
c.pool.start = 0
}
-// addpool128 adds a 128-bit constant to literal pool by two consecutive DWORD
-// instructions, the 128-bit constant is formed by ah.Offset<<64+al.Offset.
-func (c *ctxt7) addpool128(p *obj.Prog, al, ah *obj.Addr) {
- q := c.newprog()
- q.As = ADWORD
- q.To.Type = obj.TYPE_CONST
- q.To.Offset = al.Offset // q.Pc is lower than t.Pc, so al.Offset is stored in q.
-
- t := c.newprog()
- t.As = ADWORD
- t.To.Type = obj.TYPE_CONST
- t.To.Offset = ah.Offset
-
- q.Link = t
-
- if c.blitrl == nil {
- c.blitrl = q
- c.pool.start = uint32(p.Pc)
- } else {
- c.elitrl.Link = q
- }
-
- c.elitrl = t
- c.pool.size = roundUp(c.pool.size, 16)
- c.pool.size += 16
- p.Pool = q
-}
-
/*
* MOVD foo(SB), R is actually
* MOVD addr, REGTMP
sz := 4
if a.Type == obj.TYPE_CONST {
- if (lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit))) || p.As == AVMOVQ || p.As == AVMOVD {
- // out of range -0x80000000 ~ 0xffffffff or VMOVQ or VMOVD operand, must store 64-bit.
+ if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
+ // out of range -0x80000000 ~ 0xffffffff, must store 64-bit.
t.As = ADWORD
sz = 8
} // else store 32-bit
o1 = q<<30 | 0xe<<24 | len<<13 | op<<12
o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
- case 101: // VMOVQ $vcon1, $vcon2, Vd or VMOVD|VMOVS $vcon, Vd -> FMOVQ/FMOVD/FMOVS pool(PC), Vd: load from constant pool.
- o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
-
case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
o1 = c.opirr(p, p.As)
rf := p.Reg
case AMOVBU:
return LDSTR(0, 0, 1)
- case AFMOVS:
+ case AFMOVS, AVMOVS:
return LDSTR(2, 1, 1)
- case AFMOVD:
+ case AFMOVD, AVMOVD:
return LDSTR(3, 1, 1)
- case AFMOVQ:
+ case AFMOVQ, AVMOVQ:
return LDSTR(0, 1, 3)
}
break
}
- // Rewrite float constants to values stored in memory.
+ // Rewrite float and vector constants to values stored in memory.
switch p.As {
+ case AVMOVS:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int32Sym(p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AVMOVD:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int64Sym(p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AVMOVQ:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int128Sym(p.GetFrom3().Offset, p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ p.RestArgs = nil
+ }
+
case AFMOVS:
if p.From.Type == obj.TYPE_FCONST {
f64 := p.From.Val.(float64)
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
-
- break
}
if c.ctxt.Flag_dynlink {
"cmd/internal/notsha256"
"cmd/internal/objabi"
"encoding/base64"
+ "encoding/binary"
"fmt"
"internal/buildcfg"
"log"
})
}
+func (ctxt *Link) Int32Sym(i int64) *LSym {
+ name := fmt.Sprintf("$i32.%08x", uint64(i))
+ return ctxt.LookupInit(name, func(s *LSym) {
+ s.Size = 4
+ s.WriteInt(ctxt, 0, 4, i)
+ s.Type = objabi.SRODATA
+ s.Set(AttrLocal, true)
+ s.Set(AttrContentAddressable, true)
+ ctxt.constSyms = append(ctxt.constSyms, s)
+ })
+}
+
func (ctxt *Link) Int64Sym(i int64) *LSym {
name := fmt.Sprintf("$i64.%016x", uint64(i))
return ctxt.LookupInit(name, func(s *LSym) {
})
}
+func (ctxt *Link) Int128Sym(hi, lo int64) *LSym {
+ name := fmt.Sprintf("$i128.%016x%016x", uint64(hi), uint64(lo))
+ return ctxt.LookupInit(name, func(s *LSym) {
+ s.Size = 16
+ if ctxt.Arch.ByteOrder == binary.LittleEndian {
+ s.WriteInt(ctxt, 0, 8, lo)
+ s.WriteInt(ctxt, 8, 8, hi)
+ } else {
+ s.WriteInt(ctxt, 0, 8, hi)
+ s.WriteInt(ctxt, 8, 8, lo)
+ }
+ s.Type = objabi.SRODATA
+ s.Set(AttrLocal, true)
+ s.Set(AttrContentAddressable, true)
+ ctxt.constSyms = append(ctxt.constSyms, s)
+ })
+}
+
// GCLocalsSym generates a content-addressable sym containing data.
func (ctxt *Link) GCLocalsSym(data []byte) *LSym {
sum := notsha256.Sum256(data)