github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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 "github.com/gagliardetto/golang-go/cmd/compile/internal/gc" 9 "github.com/gagliardetto/golang-go/cmd/internal/obj" 10 "github.com/gagliardetto/golang-go/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 ireg := int16(s390x.REGRT2) // register holds number of remaining loop iterations 42 p = pp.Appendpp(p, s390x.AMOVD, obj.TYPE_CONST, 0, cnt/256, obj.TYPE_REG, ireg, 0) 43 p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, 256, obj.TYPE_MEM, reg, off) 44 pl := p 45 p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, 256, obj.TYPE_REG, reg, 0) 46 p = pp.Appendpp(p, s390x.ABRCTG, obj.TYPE_REG, ireg, 0, obj.TYPE_BRANCH, 0, 0) 47 gc.Patch(p, pl) 48 cnt = cnt % 256 49 } 50 51 // Generate remaining clear instructions without a loop. 52 for cnt > 0 { 53 n := cnt 54 55 // Can clear at most 256 bytes per instruction. 56 if n > 256 { 57 n = 256 58 } 59 60 switch n { 61 // Handle very small clears with move instructions. 62 case 8, 4, 2, 1: 63 ins := s390x.AMOVB 64 switch n { 65 case 8: 66 ins = s390x.AMOVD 67 case 4: 68 ins = s390x.AMOVW 69 case 2: 70 ins = s390x.AMOVH 71 } 72 p = pp.Appendpp(p, ins, obj.TYPE_CONST, 0, 0, obj.TYPE_MEM, reg, off) 73 74 // Handle clears that would require multiple move instructions with CLEAR (assembled as XC). 75 default: 76 p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, n, obj.TYPE_MEM, reg, off) 77 } 78 79 cnt -= n 80 off += n 81 } 82 83 return p 84 } 85 86 func ginsnop(pp *gc.Progs) *obj.Prog { 87 return pp.Prog(s390x.ANOPH) 88 }