...

Source file src/pkg/cmd/compile/internal/s390x/ggen.go

     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) *obj.Prog {
   108		p := pp.Prog(s390x.AWORD)
   109		p.From.Type = obj.TYPE_CONST
   110		p.From.Offset = 0x47000000 // nop 0
   111		return p
   112	}
   113	

View as plain text