github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/cmd/compile/internal/s390x/ggen.go (about) 1 // Copyright 2016 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 s390x 6 7 import ( 8 "cmd/compile/internal/gc" 9 "cmd/internal/obj" 10 "cmd/internal/obj/s390x" 11 ) 12 13 // clearLoopCutOff is the (somewhat arbitrary) value above which it is better 14 // to have a loop of clear instructions (e.g. XCs) rather than just generating 15 // multiple instructions (i.e. loop unrolling). 16 // Must be between 256 and 4096. 17 const clearLoopCutoff = 1024 18 19 // zerorange clears the stack in the given range. 20 func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog { 21 if cnt == 0 { 22 return p 23 } 24 25 // Adjust the frame to account for LR. 26 off += gc.Ctxt.FixedFrameSize() 27 reg := int16(s390x.REGSP) 28 29 // If the off cannot fit in a 12-bit unsigned displacement then we 30 // need to create a copy of the stack pointer that we can adjust. 31 // We also need to do this if we are going to loop. 32 if off < 0 || off > 4096-clearLoopCutoff || cnt > clearLoopCutoff { 33 p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, off, obj.TYPE_REG, s390x.REGRT1, 0) 34 p.Reg = int16(s390x.REGSP) 35 reg = s390x.REGRT1 36 off = 0 37 } 38 39 // Generate a loop of large clears. 40 if cnt > clearLoopCutoff { 41 n := cnt - (cnt % 256) 42 end := int16(s390x.REGRT2) 43 p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, off+n, obj.TYPE_REG, end, 0) 44 p.Reg = reg 45 p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, 256, obj.TYPE_MEM, reg, off) 46 pl := p 47 p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, 256, obj.TYPE_REG, reg, 0) 48 p = pp.Appendpp(p, s390x.ACMP, obj.TYPE_REG, reg, 0, obj.TYPE_REG, end, 0) 49 p = pp.Appendpp(p, s390x.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0) 50 gc.Patch(p, pl) 51 52 cnt -= n 53 } 54 55 // Generate remaining clear instructions without a loop. 56 for cnt > 0 { 57 n := cnt 58 59 // Can clear at most 256 bytes per instruction. 60 if n > 256 { 61 n = 256 62 } 63 64 switch n { 65 // Handle very small clears with move instructions. 66 case 8, 4, 2, 1: 67 ins := s390x.AMOVB 68 switch n { 69 case 8: 70 ins = s390x.AMOVD 71 case 4: 72 ins = s390x.AMOVW 73 case 2: 74 ins = s390x.AMOVH 75 } 76 p = pp.Appendpp(p, ins, obj.TYPE_CONST, 0, 0, obj.TYPE_MEM, reg, off) 77 78 // Handle clears that would require multiple move instructions with CLEAR (assembled as XC). 79 default: 80 p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, n, obj.TYPE_MEM, reg, off) 81 } 82 83 cnt -= n 84 off += n 85 } 86 87 return p 88 } 89 90 func zeroAuto(pp *gc.Progs, n *gc.Node) { 91 // Note: this code must not clobber any registers or the 92 // condition code. 93 sym := n.Sym.Linksym() 94 size := n.Type.Size() 95 for i := int64(0); i < size; i += int64(gc.Widthptr) { 96 p := pp.Prog(s390x.AMOVD) 97 p.From.Type = obj.TYPE_CONST 98 p.From.Offset = 0 99 p.To.Type = obj.TYPE_MEM 100 p.To.Name = obj.NAME_AUTO 101 p.To.Reg = s390x.REGSP 102 p.To.Offset = n.Xoffset + i 103 p.To.Sym = sym 104 } 105 } 106 107 func ginsnop(pp *gc.Progs) { 108 p := pp.Prog(s390x.AOR) 109 p.From.Type = obj.TYPE_REG 110 p.From.Reg = int16(s390x.REG_R0) 111 p.To.Type = obj.TYPE_REG 112 p.To.Reg = int16(s390x.REG_R0) 113 }