diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:14:23 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:14:23 +0000 |
commit | 73df946d56c74384511a194dd01dbe099584fd1a (patch) | |
tree | fd0bcea490dd81327ddfbb31e215439672c9a068 /src/cmd/internal/obj/s390x/rotate.go | |
parent | Initial commit. (diff) | |
download | golang-1.16-upstream.tar.xz golang-1.16-upstream.zip |
Adding upstream version 1.16.10.upstream/1.16.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/internal/obj/s390x/rotate.go')
-rw-r--r-- | src/cmd/internal/obj/s390x/rotate.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/cmd/internal/obj/s390x/rotate.go b/src/cmd/internal/obj/s390x/rotate.go new file mode 100644 index 0000000..388bd40 --- /dev/null +++ b/src/cmd/internal/obj/s390x/rotate.go @@ -0,0 +1,115 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package s390x + +import ( + "math/bits" +) + +// RotateParams represents the immediates required for a "rotate +// then ... selected bits instruction". +// +// The Start and End values are the indexes that represent +// the masked region. They are inclusive and are in big- +// endian order (bit 0 is the MSB, bit 63 is the LSB). They +// may wrap around. +// +// Some examples: +// +// Masked region | Start | End +// --------------------------+-------+---- +// 0x00_00_00_00_00_00_00_0f | 60 | 63 +// 0xf0_00_00_00_00_00_00_00 | 0 | 3 +// 0xf0_00_00_00_00_00_00_0f | 60 | 3 +// +// The Amount value represents the amount to rotate the +// input left by. Note that this rotation is performed +// before the masked region is used. +type RotateParams struct { + Start uint8 // big-endian start bit index [0..63] + End uint8 // big-endian end bit index [0..63] + Amount uint8 // amount to rotate left +} + +// NewRotateParams creates a set of parameters representing a +// rotation left by the amount provided and a selection of the bits +// between the provided start and end indexes (inclusive). +// +// The start and end indexes and the rotation amount must all +// be in the range 0-63 inclusive or this function will panic. +func NewRotateParams(start, end, amount uint8) RotateParams { + if start&^63 != 0 { + panic("start out of bounds") + } + if end&^63 != 0 { + panic("end out of bounds") + } + if amount&^63 != 0 { + panic("amount out of bounds") + } + return RotateParams{ + Start: start, + End: end, + Amount: amount, + } +} + +// RotateLeft generates a new set of parameters with the rotation amount +// increased by the given value. The selected bits are left unchanged. +func (r RotateParams) RotateLeft(amount uint8) RotateParams { + r.Amount += amount + r.Amount &= 63 + return r +} + +// OutMask provides a mask representing the selected bits. +func (r RotateParams) OutMask() uint64 { + // Note: z must be unsigned for bootstrap compiler + z := uint8(63-r.End+r.Start) & 63 // number of zero bits in mask + return bits.RotateLeft64(^uint64(0)<<z, -int(r.Start)) +} + +// InMask provides a mask representing the selected bits relative +// to the source value (i.e. pre-rotation). +func (r RotateParams) InMask() uint64 { + return bits.RotateLeft64(r.OutMask(), -int(r.Amount)) +} + +// OutMerge tries to generate a new set of parameters representing +// the intersection between the selected bits and the provided mask. +// If the intersection is unrepresentable (0 or not contiguous) nil +// will be returned. +func (r RotateParams) OutMerge(mask uint64) *RotateParams { + mask &= r.OutMask() + if mask == 0 { + return nil + } + + // normalize the mask so that the set bits are left aligned + o := bits.LeadingZeros64(^mask) + mask = bits.RotateLeft64(mask, o) + z := bits.LeadingZeros64(mask) + mask = bits.RotateLeft64(mask, z) + + // check that the normalized mask is contiguous + l := bits.LeadingZeros64(^mask) + if l+bits.TrailingZeros64(mask) != 64 { + return nil + } + + // update start and end positions (rotation amount remains the same) + r.Start = uint8(o+z) & 63 + r.End = (r.Start + uint8(l) - 1) & 63 + return &r +} + +// InMerge tries to generate a new set of parameters representing +// the intersection between the selected bits and the provided mask +// as applied to the source value (i.e. pre-rotation). +// If the intersection is unrepresentable (0 or not contiguous) nil +// will be returned. +func (r RotateParams) InMerge(mask uint64) *RotateParams { + return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount))) +} |