1*0fca6ea1SDimitry Andric //===-- SIDefines.h - SI Helper Functions -----------------------*- C++ -*-===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric /// \file - utility functions for the SIDefines and its common uses. 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 10*0fca6ea1SDimitry Andric 11*0fca6ea1SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H 12*0fca6ea1SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "llvm/MC/MCExpr.h" 15*0fca6ea1SDimitry Andric #include <utility> 16*0fca6ea1SDimitry Andric 17*0fca6ea1SDimitry Andric namespace llvm { 18*0fca6ea1SDimitry Andric class MCContext; 19*0fca6ea1SDimitry Andric namespace AMDGPU { 20*0fca6ea1SDimitry Andric 21*0fca6ea1SDimitry Andric /// Deduce the least significant bit aligned shift and mask values for a binary 22*0fca6ea1SDimitry Andric /// Complement \p Value (as they're defined in SIDefines.h as C_*) as a returned 23*0fca6ea1SDimitry Andric /// pair<shift, mask>. That is to say \p Value == ~(mask << shift) 24*0fca6ea1SDimitry Andric /// 25*0fca6ea1SDimitry Andric /// For example, given C_00B848_FWD_PROGRESS (i.e., 0x7FFFFFFF) from 26*0fca6ea1SDimitry Andric /// SIDefines.h, this will return the pair as (31,1). 27*0fca6ea1SDimitry Andric constexpr std::pair<unsigned, unsigned> getShiftMask(unsigned Value) { 28*0fca6ea1SDimitry Andric unsigned Shift = 0; 29*0fca6ea1SDimitry Andric unsigned Mask = 0; 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric Mask = ~Value; 32*0fca6ea1SDimitry Andric for (; !(Mask & 1); Shift++, Mask >>= 1) { 33*0fca6ea1SDimitry Andric } 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric return std::make_pair(Shift, Mask); 36*0fca6ea1SDimitry Andric } 37*0fca6ea1SDimitry Andric 38*0fca6ea1SDimitry Andric /// Provided with the MCExpr * \p Val, uint32 \p Mask and \p Shift, will return 39*0fca6ea1SDimitry Andric /// the masked and left shifted, in said order of operations, MCExpr * created 40*0fca6ea1SDimitry Andric /// within the MCContext \p Ctx. 41*0fca6ea1SDimitry Andric /// 42*0fca6ea1SDimitry Andric /// For example, given MCExpr *Val, Mask == 0xf, Shift == 6 the returned MCExpr 43*0fca6ea1SDimitry Andric /// * will be the equivalent of (Val & 0xf) << 6 44*0fca6ea1SDimitry Andric inline const MCExpr *maskShiftSet(const MCExpr *Val, uint32_t Mask, 45*0fca6ea1SDimitry Andric uint32_t Shift, MCContext &Ctx) { 46*0fca6ea1SDimitry Andric if (Mask) { 47*0fca6ea1SDimitry Andric const MCExpr *MaskExpr = MCConstantExpr::create(Mask, Ctx); 48*0fca6ea1SDimitry Andric Val = MCBinaryExpr::createAnd(Val, MaskExpr, Ctx); 49*0fca6ea1SDimitry Andric } 50*0fca6ea1SDimitry Andric if (Shift) { 51*0fca6ea1SDimitry Andric const MCExpr *ShiftExpr = MCConstantExpr::create(Shift, Ctx); 52*0fca6ea1SDimitry Andric Val = MCBinaryExpr::createShl(Val, ShiftExpr, Ctx); 53*0fca6ea1SDimitry Andric } 54*0fca6ea1SDimitry Andric return Val; 55*0fca6ea1SDimitry Andric } 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric /// Provided with the MCExpr * \p Val, uint32 \p Mask and \p Shift, will return 58*0fca6ea1SDimitry Andric /// the right shifted and masked, in said order of operations, MCExpr * created 59*0fca6ea1SDimitry Andric /// within the MCContext \p Ctx. 60*0fca6ea1SDimitry Andric /// 61*0fca6ea1SDimitry Andric /// For example, given MCExpr *Val, Mask == 0xf, Shift == 6 the returned MCExpr 62*0fca6ea1SDimitry Andric /// * will be the equivalent of (Val >> 6) & 0xf 63*0fca6ea1SDimitry Andric inline const MCExpr *maskShiftGet(const MCExpr *Val, uint32_t Mask, 64*0fca6ea1SDimitry Andric uint32_t Shift, MCContext &Ctx) { 65*0fca6ea1SDimitry Andric if (Shift) { 66*0fca6ea1SDimitry Andric const MCExpr *ShiftExpr = MCConstantExpr::create(Shift, Ctx); 67*0fca6ea1SDimitry Andric Val = MCBinaryExpr::createLShr(Val, ShiftExpr, Ctx); 68*0fca6ea1SDimitry Andric } 69*0fca6ea1SDimitry Andric if (Mask) { 70*0fca6ea1SDimitry Andric const MCExpr *MaskExpr = MCConstantExpr::create(Mask, Ctx); 71*0fca6ea1SDimitry Andric Val = MCBinaryExpr::createAnd(Val, MaskExpr, Ctx); 72*0fca6ea1SDimitry Andric } 73*0fca6ea1SDimitry Andric return Val; 74*0fca6ea1SDimitry Andric } 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric } // end namespace AMDGPU 77*0fca6ea1SDimitry Andric } // end namespace llvm 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_UTILS_SIDEFINESUTILS_H 80