1// Copyright 2019 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 5package s390x 6 7import ( 8 "math/bits" 9) 10 11// RotateParams represents the immediates required for a "rotate 12// then ... selected bits instruction". 13// 14// The Start and End values are the indexes that represent 15// the masked region. They are inclusive and are in big- 16// endian order (bit 0 is the MSB, bit 63 is the LSB). They 17// may wrap around. 18// 19// Some examples: 20// 21// Masked region | Start | End 22// --------------------------+-------+---- 23// 0x00_00_00_00_00_00_00_0f | 60 | 63 24// 0xf0_00_00_00_00_00_00_00 | 0 | 3 25// 0xf0_00_00_00_00_00_00_0f | 60 | 3 26// 27// The Amount value represents the amount to rotate the 28// input left by. Note that this rotation is performed 29// before the masked region is used. 30type RotateParams struct { 31 Start uint8 // big-endian start bit index [0..63] 32 End uint8 // big-endian end bit index [0..63] 33 Amount uint8 // amount to rotate left 34} 35 36// NewRotateParams creates a set of parameters representing a 37// rotation left by the amount provided and a selection of the bits 38// between the provided start and end indexes (inclusive). 39// 40// The start and end indexes and the rotation amount must all 41// be in the range 0-63 inclusive or this function will panic. 42func NewRotateParams(start, end, amount uint8) RotateParams { 43 if start&^63 != 0 { 44 panic("start out of bounds") 45 } 46 if end&^63 != 0 { 47 panic("end out of bounds") 48 } 49 if amount&^63 != 0 { 50 panic("amount out of bounds") 51 } 52 return RotateParams{ 53 Start: start, 54 End: end, 55 Amount: amount, 56 } 57} 58 59// RotateLeft generates a new set of parameters with the rotation amount 60// increased by the given value. The selected bits are left unchanged. 61func (r RotateParams) RotateLeft(amount uint8) RotateParams { 62 r.Amount += amount 63 r.Amount &= 63 64 return r 65} 66 67// OutMask provides a mask representing the selected bits. 68func (r RotateParams) OutMask() uint64 { 69 // Note: z must be unsigned for bootstrap compiler 70 z := uint8(63-r.End+r.Start) & 63 // number of zero bits in mask 71 return bits.RotateLeft64(^uint64(0)<<z, -int(r.Start)) 72} 73 74// InMask provides a mask representing the selected bits relative 75// to the source value (i.e. pre-rotation). 76func (r RotateParams) InMask() uint64 { 77 return bits.RotateLeft64(r.OutMask(), -int(r.Amount)) 78} 79 80// OutMerge tries to generate a new set of parameters representing 81// the intersection between the selected bits and the provided mask. 82// If the intersection is unrepresentable (0 or not contiguous) nil 83// will be returned. 84func (r RotateParams) OutMerge(mask uint64) *RotateParams { 85 mask &= r.OutMask() 86 if mask == 0 { 87 return nil 88 } 89 90 // normalize the mask so that the set bits are left aligned 91 o := bits.LeadingZeros64(^mask) 92 mask = bits.RotateLeft64(mask, o) 93 z := bits.LeadingZeros64(mask) 94 mask = bits.RotateLeft64(mask, z) 95 96 // check that the normalized mask is contiguous 97 l := bits.LeadingZeros64(^mask) 98 if l+bits.TrailingZeros64(mask) != 64 { 99 return nil 100 } 101 102 // update start and end positions (rotation amount remains the same) 103 r.Start = uint8(o+z) & 63 104 r.End = (r.Start + uint8(l) - 1) & 63 105 return &r 106} 107 108// InMerge tries to generate a new set of parameters representing 109// the intersection between the selected bits and the provided mask 110// as applied to the source value (i.e. pre-rotation). 111// If the intersection is unrepresentable (0 or not contiguous) nil 112// will be returned. 113func (r RotateParams) InMerge(mask uint64) *RotateParams { 114 return r.OutMerge(bits.RotateLeft64(mask, int(r.Amount))) 115} 116 117func (RotateParams) CanBeAnSSAAux() {} 118