github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/compile/internal/arm64/ggen.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package arm64 6 7 import ( 8 "cmd/compile/internal/gc" 9 "cmd/internal/obj" 10 "cmd/internal/obj/arm64" 11 ) 12 13 func defframe(pp *gc.Progs, fn *gc.Node, sz int64) { 14 // fill in argument size, stack size 15 pp.Text.To.Type = obj.TYPE_TEXTSIZE 16 17 pp.Text.To.Val = int32(gc.Rnd(fn.Type.ArgWidth(), int64(gc.Widthptr))) 18 frame := uint32(gc.Rnd(sz, int64(gc.Widthreg))) 19 20 // arm64 requires that the frame size (not counting saved LR) 21 // be empty or be 8 mod 16. If not, pad it. 22 if frame != 0 && frame%16 != 8 { 23 frame += 8 24 } 25 26 pp.Text.To.Offset = int64(frame) 27 28 // insert code to zero ambiguously live variables 29 // so that the garbage collector only sees initialized values 30 // when it looks for pointers. 31 p := pp.Text 32 33 hi := int64(0) 34 lo := hi 35 36 // iterate through declarations - they are sorted in decreasing xoffset order. 37 for _, n := range fn.Func.Dcl { 38 if !n.Name.Needzero() { 39 continue 40 } 41 if n.Class != gc.PAUTO { 42 gc.Fatalf("needzero class %d", n.Class) 43 } 44 if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 { 45 gc.Fatalf("var %L has size %d offset %d", n, int(n.Type.Width), int(n.Xoffset)) 46 } 47 48 if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) { 49 // merge with range we already have 50 lo = n.Xoffset 51 52 continue 53 } 54 55 // zero old range 56 p = zerorange(pp, p, int64(frame), lo, hi) 57 58 // set new range 59 hi = n.Xoffset + n.Type.Width 60 61 lo = n.Xoffset 62 } 63 64 // zero final range 65 zerorange(pp, p, int64(frame), lo, hi) 66 } 67 68 var darwin = obj.GOOS == "darwin" 69 70 func zerorange(pp *gc.Progs, p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog { 71 cnt := hi - lo 72 if cnt == 0 { 73 return p 74 } 75 if cnt < int64(4*gc.Widthptr) { 76 for i := int64(0); i < cnt; i += int64(gc.Widthptr) { 77 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGSP, 8+frame+lo+i) 78 } 79 } else if cnt <= int64(128*gc.Widthptr) && !darwin { // darwin ld64 cannot handle BR26 reloc with non-zero addend 80 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 81 p = pp.Appendpp(p, arm64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, arm64.REGRT1, 0) 82 p.Reg = arm64.REGRT1 83 p = pp.Appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0) 84 p.To.Name = obj.NAME_EXTERN 85 p.To.Sym = gc.Duffzero 86 p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr)) 87 } else { 88 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, arm64.REGTMP, 0) 89 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 90 p = pp.Appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 91 p.Reg = arm64.REGRT1 92 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, arm64.REGTMP, 0) 93 p = pp.Appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT2, 0) 94 p.Reg = arm64.REGRT1 95 p = pp.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGRT1, int64(gc.Widthptr)) 96 p.Scond = arm64.C_XPRE 97 p1 := p 98 p = pp.Appendpp(p, arm64.ACMP, obj.TYPE_REG, arm64.REGRT1, 0, obj.TYPE_NONE, 0, 0) 99 p.Reg = arm64.REGRT2 100 p = pp.Appendpp(p, arm64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0) 101 gc.Patch(p, p1) 102 } 103 104 return p 105 } 106 107 func ginsnop(pp *gc.Progs) { 108 p := pp.Prog(arm64.AHINT) 109 p.From.Type = obj.TYPE_CONST 110 }