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(ptxt *obj.Prog) { 14 // fill in argument size, stack size 15 ptxt.To.Type = obj.TYPE_TEXTSIZE 16 17 ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.ArgWidth(), int64(gc.Widthptr))) 18 frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, 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 ptxt.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 := ptxt 32 33 hi := int64(0) 34 lo := hi 35 36 // iterate through declarations - they are sorted in decreasing xoffset order. 37 for _, n := range gc.Curfn.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(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(p, int64(frame), lo, hi) 66 } 67 68 var darwin = obj.GOOS == "darwin" 69 70 func zerorange(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 = gc.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 = gc.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 81 p = gc.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 = gc.Appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0) 84 gc.Naddr(&p.To, gc.Sysfunc("duffzero")) 85 p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr)) 86 } else { 87 p = gc.Appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, arm64.REGTMP, 0) 88 p = gc.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGSP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 89 p = gc.Appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT1, 0) 90 p.Reg = arm64.REGRT1 91 p = gc.Appendpp(p, arm64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, arm64.REGTMP, 0) 92 p = gc.Appendpp(p, arm64.AADD, obj.TYPE_REG, arm64.REGTMP, 0, obj.TYPE_REG, arm64.REGRT2, 0) 93 p.Reg = arm64.REGRT1 94 p = gc.Appendpp(p, arm64.AMOVD, obj.TYPE_REG, arm64.REGZERO, 0, obj.TYPE_MEM, arm64.REGRT1, int64(gc.Widthptr)) 95 p.Scond = arm64.C_XPRE 96 p1 := p 97 p = gc.Appendpp(p, arm64.ACMP, obj.TYPE_REG, arm64.REGRT1, 0, obj.TYPE_NONE, 0, 0) 98 p.Reg = arm64.REGRT2 99 p = gc.Appendpp(p, arm64.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0) 100 gc.Patch(p, p1) 101 } 102 103 return p 104 } 105 106 func ginsnop() { 107 p := gc.Prog(arm64.AHINT) 108 p.From.Type = obj.TYPE_CONST 109 } 110