vec_reg.hh revision 12334
112108SRekai.GonzalezAlberquilla@arm.com/* 212108SRekai.GonzalezAlberquilla@arm.com * Copyright (c) 2015-2016 ARM Limited 312108SRekai.GonzalezAlberquilla@arm.com * All rights reserved 412108SRekai.GonzalezAlberquilla@arm.com * 512108SRekai.GonzalezAlberquilla@arm.com * The license below extends only to copyright in the software and shall 612108SRekai.GonzalezAlberquilla@arm.com * not be construed as granting a license to any other intellectual 712108SRekai.GonzalezAlberquilla@arm.com * property including but not limited to intellectual property relating 812108SRekai.GonzalezAlberquilla@arm.com * to a hardware implementation of the functionality of the software 912108SRekai.GonzalezAlberquilla@arm.com * licensed hereunder. You may use the software subject to the license 1012108SRekai.GonzalezAlberquilla@arm.com * terms below provided that you ensure that this notice is replicated 1112108SRekai.GonzalezAlberquilla@arm.com * unmodified and in its entirety in all distributions of the software, 1212108SRekai.GonzalezAlberquilla@arm.com * modified or unmodified, in source code or in binary form. 1312108SRekai.GonzalezAlberquilla@arm.com * 1412108SRekai.GonzalezAlberquilla@arm.com * Redistribution and use in source and binary forms, with or without 1512108SRekai.GonzalezAlberquilla@arm.com * modification, are permitted provided that the following conditions are 1612108SRekai.GonzalezAlberquilla@arm.com * met: redistributions of source code must retain the above copyright 1712108SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer; 1812108SRekai.GonzalezAlberquilla@arm.com * redistributions in binary form must reproduce the above copyright 1912108SRekai.GonzalezAlberquilla@arm.com * notice, this list of conditions and the following disclaimer in the 2012108SRekai.GonzalezAlberquilla@arm.com * documentation and/or other materials provided with the distribution; 2112108SRekai.GonzalezAlberquilla@arm.com * neither the name of the copyright holders nor the names of its 2212108SRekai.GonzalezAlberquilla@arm.com * contributors may be used to endorse or promote products derived from 2312108SRekai.GonzalezAlberquilla@arm.com * this software without specific prior written permission. 2412108SRekai.GonzalezAlberquilla@arm.com * 2512108SRekai.GonzalezAlberquilla@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612108SRekai.GonzalezAlberquilla@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712108SRekai.GonzalezAlberquilla@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812108SRekai.GonzalezAlberquilla@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912108SRekai.GonzalezAlberquilla@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012108SRekai.GonzalezAlberquilla@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112108SRekai.GonzalezAlberquilla@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212108SRekai.GonzalezAlberquilla@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312108SRekai.GonzalezAlberquilla@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412108SRekai.GonzalezAlberquilla@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3512108SRekai.GonzalezAlberquilla@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612108SRekai.GonzalezAlberquilla@arm.com * 3712108SRekai.GonzalezAlberquilla@arm.com * Authors: Giacomo Gabrielli 3812108SRekai.GonzalezAlberquilla@arm.com * Nathanael Premillieu 3912108SRekai.GonzalezAlberquilla@arm.com * Rekai Gonzalez 4012108SRekai.GonzalezAlberquilla@arm.com */ 4112108SRekai.GonzalezAlberquilla@arm.com 4212108SRekai.GonzalezAlberquilla@arm.com/** \file arch/generic/vec_reg.hh 4312108SRekai.GonzalezAlberquilla@arm.com * Vector Registers layout specification. 4412108SRekai.GonzalezAlberquilla@arm.com * 4512108SRekai.GonzalezAlberquilla@arm.com * This register type is to be used to model the SIMD registers. 4612108SRekai.GonzalezAlberquilla@arm.com * It takes into account the possibility that different architectural names 4712108SRekai.GonzalezAlberquilla@arm.com * may overlap (like for ARMv8 AArch32 for example). 4812108SRekai.GonzalezAlberquilla@arm.com * 4912108SRekai.GonzalezAlberquilla@arm.com * The design is having a basic vector register container that holds the 5012108SRekai.GonzalezAlberquilla@arm.com * bytes, unaware of anything else. This is implemented by VecRegContainer. 5112108SRekai.GonzalezAlberquilla@arm.com * As the (maximum) length of the physical vector register is a compile-time 5212108SRekai.GonzalezAlberquilla@arm.com * constant, it is defined as a template parameter. 5312108SRekai.GonzalezAlberquilla@arm.com * 5412108SRekai.GonzalezAlberquilla@arm.com * This file also describes two views of the container that have semantic 5512108SRekai.GonzalezAlberquilla@arm.com * information about the bytes. The first of this views is VecRegT. 5612108SRekai.GonzalezAlberquilla@arm.com * A VecRegT is a view of a VecRegContainer (by reference). The VecRegT has 5712108SRekai.GonzalezAlberquilla@arm.com * a type (VecElem) to which bytes are casted, and the amount of such 5812108SRekai.GonzalezAlberquilla@arm.com * elements that the vector contains (NumElems). The size of a view, 5912108SRekai.GonzalezAlberquilla@arm.com * calculated as sizeof(VecElem) * NumElems must match the size of the 6012108SRekai.GonzalezAlberquilla@arm.com * underlying container. As VecRegT has some degree of type information it 6112108SRekai.GonzalezAlberquilla@arm.com * has vector semantics, and defines the index operator ([]) to get 6212108SRekai.GonzalezAlberquilla@arm.com * references to particular bytes understood as a VecElem. 6312108SRekai.GonzalezAlberquilla@arm.com * The second view of a container implemented in this file is VecLaneT, which 6412108SRekai.GonzalezAlberquilla@arm.com * is a view of a subset of the container. 6512108SRekai.GonzalezAlberquilla@arm.com * A VecLaneT is a view of a lane of a vector register, where a lane is 6612108SRekai.GonzalezAlberquilla@arm.com * identified by a type (VecElem) and an index (although the view is 6712108SRekai.GonzalezAlberquilla@arm.com * unaware of its index). Operations on the lane are directly applied to 6812108SRekai.GonzalezAlberquilla@arm.com * the corresponding bytes of the underlying VecRegContainer through a 6912108SRekai.GonzalezAlberquilla@arm.com * reference. 7012108SRekai.GonzalezAlberquilla@arm.com * 7112108SRekai.GonzalezAlberquilla@arm.com * The intended usage is requesting views to the VecRegContainer via the 7212108SRekai.GonzalezAlberquilla@arm.com * member 'as' for VecRegT and the member 'laneView' for VecLaneT. Kindly 7312108SRekai.GonzalezAlberquilla@arm.com * find an example of usage in the following. 7412108SRekai.GonzalezAlberquilla@arm.com * 7512108SRekai.GonzalezAlberquilla@arm.com * 7612108SRekai.GonzalezAlberquilla@arm.com * // We declare 512 bits vectors 7712108SRekai.GonzalezAlberquilla@arm.com * using Vec512 = VecRegContainer<64>; 7812108SRekai.GonzalezAlberquilla@arm.com * ... 7912108SRekai.GonzalezAlberquilla@arm.com * // We implement the physical vector register file 8012108SRekai.GonzalezAlberquilla@arm.com * Vec512 physicalVecRegFile[NUM_VREGS]; 8112108SRekai.GonzalezAlberquilla@arm.com * ... 8212108SRekai.GonzalezAlberquilla@arm.com * // Usage example, for a macro op: 8312108SRekai.GonzalezAlberquilla@arm.com * VecFloat8Add(ExecContext* xd) { 8412108SRekai.GonzalezAlberquilla@arm.com * // Request source vector register to the execution context (const as it 8512108SRekai.GonzalezAlberquilla@arm.com * // is read only). 8612108SRekai.GonzalezAlberquilla@arm.com * const Vec512& vsrc1raw = xc->readVecRegOperand(this, 0); 8712108SRekai.GonzalezAlberquilla@arm.com * // View it as a vector of floats (we could just specify the first 8812108SRekai.GonzalezAlberquilla@arm.com * // template parametre, the second has a default value that works, and the 8912108SRekai.GonzalezAlberquilla@arm.com * // last one is derived by the constness of vsrc1raw). 9012108SRekai.GonzalezAlberquilla@arm.com * VecRegT<float, 8, true>& vsrc1 = vsrc1raw->as<float, 8>(); 9112108SRekai.GonzalezAlberquilla@arm.com * 9212108SRekai.GonzalezAlberquilla@arm.com * // Second source and view 9312108SRekai.GonzalezAlberquilla@arm.com * const Vec512& vsrc2raw = xc->readVecRegOperand(this, 1); 9412108SRekai.GonzalezAlberquilla@arm.com * VecRegT<float, 8, true>& vsrc2 = vsrc2raw->as<float, 8>(); 9512108SRekai.GonzalezAlberquilla@arm.com * 9612108SRekai.GonzalezAlberquilla@arm.com * // Destination and view 9712108SRekai.GonzalezAlberquilla@arm.com * Vec512 vdstraw; 9812108SRekai.GonzalezAlberquilla@arm.com * VecRegT<float, 8, false>& vdst = vdstraw->as<float, 8>(); 9912108SRekai.GonzalezAlberquilla@arm.com * 10012108SRekai.GonzalezAlberquilla@arm.com * for (auto i = 0; i < 8; i++) { 10112108SRekai.GonzalezAlberquilla@arm.com * // This asignment sets the bits in the underlying Vec512: vdstraw 10212108SRekai.GonzalezAlberquilla@arm.com * vdst[i] = vsrc1[i] + vsrc2[i]; 10312108SRekai.GonzalezAlberquilla@arm.com * } 10412108SRekai.GonzalezAlberquilla@arm.com * xc->setWriteRegOperand(this, 0, vdstraw); 10512108SRekai.GonzalezAlberquilla@arm.com * } 10612108SRekai.GonzalezAlberquilla@arm.com * 10712108SRekai.GonzalezAlberquilla@arm.com * // Usage example, for a micro op that operates over lane number _lidx: 10812108SRekai.GonzalezAlberquilla@arm.com * VecFloatLaneAdd(ExecContext* xd) { 10912108SRekai.GonzalezAlberquilla@arm.com * // Request source vector register to the execution context (const as it 11012108SRekai.GonzalezAlberquilla@arm.com * // is read only). 11112108SRekai.GonzalezAlberquilla@arm.com * const Vec512& vsrc1raw = xc->readVecRegOperand(this, 0); 11212108SRekai.GonzalezAlberquilla@arm.com * // View it as a lane of a vector of floats (we could just specify the 11312108SRekai.GonzalezAlberquilla@arm.com * // first template parametre, the second is derived by the constness of 11412108SRekai.GonzalezAlberquilla@arm.com * // vsrc1raw). 11512108SRekai.GonzalezAlberquilla@arm.com * VecLaneT<float, true>& src1 = vsrc1raw->laneView<float>(this->_lidx); 11612108SRekai.GonzalezAlberquilla@arm.com * 11712108SRekai.GonzalezAlberquilla@arm.com * // Second source and view 11812108SRekai.GonzalezAlberquilla@arm.com * const Vec512& vsrc2raw = xc->readVecRegOperand(this, 1); 11912108SRekai.GonzalezAlberquilla@arm.com * VecLaneT<float, true>& src2 = vsrc2raw->laneView<float>(this->_lidx); 12012108SRekai.GonzalezAlberquilla@arm.com * 12112108SRekai.GonzalezAlberquilla@arm.com * // (Writable) destination and view 12212108SRekai.GonzalezAlberquilla@arm.com * // As this is a partial write, we need the exec context to support that 12312108SRekai.GonzalezAlberquilla@arm.com * // through, e.g., 'readVecRegOperandToWrite' returning a writable 12412108SRekai.GonzalezAlberquilla@arm.com * // reference to the register 12512108SRekai.GonzalezAlberquilla@arm.com * Vec512 vdstraw = xc->readVecRegOperandToWrite(this, 3); 12612108SRekai.GonzalezAlberquilla@arm.com * VecLaneT<float, false>& dst = vdstraw->laneView<float>(this->_lidx); 12712108SRekai.GonzalezAlberquilla@arm.com * 12812108SRekai.GonzalezAlberquilla@arm.com * dst = src1 + src2; 12912108SRekai.GonzalezAlberquilla@arm.com * // There is no need to copy the value back into the exec context, as 13012108SRekai.GonzalezAlberquilla@arm.com * // the assignment to dst modifies the appropriate bytes in vdstraw which 13112108SRekai.GonzalezAlberquilla@arm.com * // is in turn, a reference to the register in the cpu model. 13212108SRekai.GonzalezAlberquilla@arm.com * // For operations that do conditional writeback, we can decouple the 13312108SRekai.GonzalezAlberquilla@arm.com * // write by doing: 13412108SRekai.GonzalezAlberquilla@arm.com * // auto tmp = src1 + src2; 13512108SRekai.GonzalezAlberquilla@arm.com * // if (test) { 13612108SRekai.GonzalezAlberquilla@arm.com * // dst = tmp; // do writeback 13712108SRekai.GonzalezAlberquilla@arm.com * // } else { 13812108SRekai.GonzalezAlberquilla@arm.com * // // do not do writeback 13912108SRekai.GonzalezAlberquilla@arm.com * // } 14012108SRekai.GonzalezAlberquilla@arm.com * } 14112108SRekai.GonzalezAlberquilla@arm.com * 14212108SRekai.GonzalezAlberquilla@arm.com */ 14312108SRekai.GonzalezAlberquilla@arm.com 14412108SRekai.GonzalezAlberquilla@arm.com#ifndef __ARCH_GENERIC_VEC_REG_HH__ 14512108SRekai.GonzalezAlberquilla@arm.com#define __ARCH_GENERIC_VEC_REG_HH__ 14612108SRekai.GonzalezAlberquilla@arm.com 14712108SRekai.GonzalezAlberquilla@arm.com#include <array> 14812108SRekai.GonzalezAlberquilla@arm.com#include <cassert> 14912108SRekai.GonzalezAlberquilla@arm.com#include <iostream> 15012108SRekai.GonzalezAlberquilla@arm.com#include <string> 15112108SRekai.GonzalezAlberquilla@arm.com#include <type_traits> 15212108SRekai.GonzalezAlberquilla@arm.com#include <vector> 15312108SRekai.GonzalezAlberquilla@arm.com 15412108SRekai.GonzalezAlberquilla@arm.com#include "base/cprintf.hh" 15512334Sgabeblack@google.com#include "base/logging.hh" 15612108SRekai.GonzalezAlberquilla@arm.com 15712108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 15812108SRekai.GonzalezAlberquilla@arm.comclass VecRegContainer; 15912108SRekai.GonzalezAlberquilla@arm.com 16012108SRekai.GonzalezAlberquilla@arm.com/** Vector Register Abstraction 16112108SRekai.GonzalezAlberquilla@arm.com * This generic class is a view in a particularization of MVC, to vector 16212108SRekai.GonzalezAlberquilla@arm.com * registers. There is a VecRegContainer that implements the model, and 16312108SRekai.GonzalezAlberquilla@arm.com * contains the data. To that model we can interpose different instantiations 16412108SRekai.GonzalezAlberquilla@arm.com * of VecRegT to view the container as a vector of NumElems elems of type 16512108SRekai.GonzalezAlberquilla@arm.com * VecElem. 16612108SRekai.GonzalezAlberquilla@arm.com * @tparam VecElem Type of each element of the vector. 16712108SRekai.GonzalezAlberquilla@arm.com * @tparam NumElems Amount of components of the vector. 16812108SRekai.GonzalezAlberquilla@arm.com * @tparam Const Indicate if the underlying container can be modified through 16912108SRekai.GonzalezAlberquilla@arm.com * the view. 17012108SRekai.GonzalezAlberquilla@arm.com */ 17112108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem, size_t NumElems, bool Const> 17212108SRekai.GonzalezAlberquilla@arm.comclass VecRegT 17312108SRekai.GonzalezAlberquilla@arm.com{ 17412108SRekai.GonzalezAlberquilla@arm.com /** Size of the register in bytes. */ 17512108SRekai.GonzalezAlberquilla@arm.com static constexpr size_t SIZE = sizeof(VecElem) * NumElems; 17612108SRekai.GonzalezAlberquilla@arm.com public: 17712108SRekai.GonzalezAlberquilla@arm.com /** Container type alias. */ 17812108SRekai.GonzalezAlberquilla@arm.com using Container = typename std::conditional<Const, 17912108SRekai.GonzalezAlberquilla@arm.com const VecRegContainer<SIZE>, 18012108SRekai.GonzalezAlberquilla@arm.com VecRegContainer<SIZE>>::type; 18112108SRekai.GonzalezAlberquilla@arm.com private: 18212108SRekai.GonzalezAlberquilla@arm.com /** My type alias. */ 18312108SRekai.GonzalezAlberquilla@arm.com using MyClass = VecRegT<VecElem, NumElems, Const>; 18412108SRekai.GonzalezAlberquilla@arm.com /** Reference to container. */ 18512108SRekai.GonzalezAlberquilla@arm.com Container& container; 18612108SRekai.GonzalezAlberquilla@arm.com 18712108SRekai.GonzalezAlberquilla@arm.com public: 18812108SRekai.GonzalezAlberquilla@arm.com /** Constructor. */ 18912108SRekai.GonzalezAlberquilla@arm.com VecRegT(Container& cnt) : container(cnt) {}; 19012108SRekai.GonzalezAlberquilla@arm.com 19112108SRekai.GonzalezAlberquilla@arm.com /** Zero the container. */ 19212108SRekai.GonzalezAlberquilla@arm.com template<bool Condition = !Const> 19312108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<Condition, void>::type 19412108SRekai.GonzalezAlberquilla@arm.com zero() { container.zero(); } 19512108SRekai.GonzalezAlberquilla@arm.com 19612108SRekai.GonzalezAlberquilla@arm.com template<bool Condition = !Const> 19712108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<Condition, MyClass&>::type 19812108SRekai.GonzalezAlberquilla@arm.com operator=(const MyClass& that) 19912108SRekai.GonzalezAlberquilla@arm.com { 20012108SRekai.GonzalezAlberquilla@arm.com container = that.container; 20112108SRekai.GonzalezAlberquilla@arm.com return *this; 20212108SRekai.GonzalezAlberquilla@arm.com } 20312108SRekai.GonzalezAlberquilla@arm.com 20412108SRekai.GonzalezAlberquilla@arm.com /** Index operator. */ 20512108SRekai.GonzalezAlberquilla@arm.com const VecElem& operator[](size_t idx) const 20612108SRekai.GonzalezAlberquilla@arm.com { 20712108SRekai.GonzalezAlberquilla@arm.com return container.template raw_ptr<VecElem>()[idx]; 20812108SRekai.GonzalezAlberquilla@arm.com } 20912108SRekai.GonzalezAlberquilla@arm.com 21012108SRekai.GonzalezAlberquilla@arm.com /** Index operator. */ 21112108SRekai.GonzalezAlberquilla@arm.com template<bool Condition = !Const> 21212108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<Condition, VecElem&>::type 21312108SRekai.GonzalezAlberquilla@arm.com operator[](size_t idx) 21412108SRekai.GonzalezAlberquilla@arm.com { 21512108SRekai.GonzalezAlberquilla@arm.com return container.template raw_ptr<VecElem>()[idx]; 21612108SRekai.GonzalezAlberquilla@arm.com } 21712108SRekai.GonzalezAlberquilla@arm.com 21812108SRekai.GonzalezAlberquilla@arm.com /** Equality operator. 21912108SRekai.GonzalezAlberquilla@arm.com * Required to compare thread contexts. 22012108SRekai.GonzalezAlberquilla@arm.com */ 22112108SRekai.GonzalezAlberquilla@arm.com template<typename VE2, size_t NE2, bool C2> 22212108SRekai.GonzalezAlberquilla@arm.com bool 22312108SRekai.GonzalezAlberquilla@arm.com operator==(const VecRegT<VE2, NE2, C2>& that) const 22412108SRekai.GonzalezAlberquilla@arm.com { 22512108SRekai.GonzalezAlberquilla@arm.com return container == that.container; 22612108SRekai.GonzalezAlberquilla@arm.com } 22712108SRekai.GonzalezAlberquilla@arm.com /** Inequality operator. 22812108SRekai.GonzalezAlberquilla@arm.com * Required to compare thread contexts. 22912108SRekai.GonzalezAlberquilla@arm.com */ 23012108SRekai.GonzalezAlberquilla@arm.com template<typename VE2, size_t NE2, bool C2> 23112108SRekai.GonzalezAlberquilla@arm.com bool 23212108SRekai.GonzalezAlberquilla@arm.com operator!=(const VecRegT<VE2, NE2, C2>& that) const 23312108SRekai.GonzalezAlberquilla@arm.com { 23412108SRekai.GonzalezAlberquilla@arm.com return !operator==(that); 23512108SRekai.GonzalezAlberquilla@arm.com } 23612108SRekai.GonzalezAlberquilla@arm.com 23712108SRekai.GonzalezAlberquilla@arm.com /** Output stream operator. */ 23812108SRekai.GonzalezAlberquilla@arm.com friend std::ostream& 23912108SRekai.GonzalezAlberquilla@arm.com operator<<(std::ostream& os, const MyClass& vr) 24012108SRekai.GonzalezAlberquilla@arm.com { 24112108SRekai.GonzalezAlberquilla@arm.com /* 0-sized is not allowed */ 24212108SRekai.GonzalezAlberquilla@arm.com os << "[" << std::hex << (uint32_t)vr[0]; 24312108SRekai.GonzalezAlberquilla@arm.com for (uint32_t e = 1; e < vr.SIZE; e++) 24412108SRekai.GonzalezAlberquilla@arm.com os << " " << std::hex << (uint32_t)vr[e]; 24512108SRekai.GonzalezAlberquilla@arm.com os << ']'; 24612108SRekai.GonzalezAlberquilla@arm.com return os; 24712108SRekai.GonzalezAlberquilla@arm.com } 24812108SRekai.GonzalezAlberquilla@arm.com 24912108SRekai.GonzalezAlberquilla@arm.com const std::string print() const { return csprintf("%s", *this); } 25012108SRekai.GonzalezAlberquilla@arm.com /** 25112108SRekai.GonzalezAlberquilla@arm.com * Cast to VecRegContainer& 25212108SRekai.GonzalezAlberquilla@arm.com * It is useful to get the reference to the container for ISA tricks, 25312108SRekai.GonzalezAlberquilla@arm.com * because casting to reference prevents unnecessary copies. 25412108SRekai.GonzalezAlberquilla@arm.com */ 25512108SRekai.GonzalezAlberquilla@arm.com operator Container&() { return container; } 25612108SRekai.GonzalezAlberquilla@arm.com}; 25712108SRekai.GonzalezAlberquilla@arm.com 25812108SRekai.GonzalezAlberquilla@arm.com/* Forward declaration. */ 25912108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem, bool Const> 26012108SRekai.GonzalezAlberquilla@arm.comclass VecLaneT; 26112108SRekai.GonzalezAlberquilla@arm.com 26212108SRekai.GonzalezAlberquilla@arm.com/** 26312108SRekai.GonzalezAlberquilla@arm.com * Vector Register Abstraction 26412108SRekai.GonzalezAlberquilla@arm.com * This generic class is the model in a particularization of MVC, to vector 26512108SRekai.GonzalezAlberquilla@arm.com * registers. The model has functionality to create views of itself, or a 26612108SRekai.GonzalezAlberquilla@arm.com * portion through the method 'as 26712108SRekai.GonzalezAlberquilla@arm.com * @tparam Sz Size of the container in bytes. 26812108SRekai.GonzalezAlberquilla@arm.com */ 26912108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 27012108SRekai.GonzalezAlberquilla@arm.comclass VecRegContainer 27112108SRekai.GonzalezAlberquilla@arm.com{ 27212108SRekai.GonzalezAlberquilla@arm.com static_assert(Sz > 0, 27312108SRekai.GonzalezAlberquilla@arm.com "Cannot create Vector Register Container of zero size"); 27412108SRekai.GonzalezAlberquilla@arm.com public: 27512108SRekai.GonzalezAlberquilla@arm.com static constexpr size_t SIZE = Sz; 27612108SRekai.GonzalezAlberquilla@arm.com using Container = std::array<uint8_t,Sz>; 27712108SRekai.GonzalezAlberquilla@arm.com private: 27812108SRekai.GonzalezAlberquilla@arm.com Container container; 27912108SRekai.GonzalezAlberquilla@arm.com using MyClass = VecRegContainer<SIZE>; 28012108SRekai.GonzalezAlberquilla@arm.com 28112108SRekai.GonzalezAlberquilla@arm.com public: 28212108SRekai.GonzalezAlberquilla@arm.com VecRegContainer() {} 28312108SRekai.GonzalezAlberquilla@arm.com /* This is required for de-serialisation. */ 28412108SRekai.GonzalezAlberquilla@arm.com VecRegContainer(const std::vector<uint8_t>& that) 28512108SRekai.GonzalezAlberquilla@arm.com { 28612108SRekai.GonzalezAlberquilla@arm.com assert(that.size() >= SIZE); 28712108SRekai.GonzalezAlberquilla@arm.com std::memcpy(container.data(), &that[0], SIZE); 28812108SRekai.GonzalezAlberquilla@arm.com } 28912108SRekai.GonzalezAlberquilla@arm.com 29012108SRekai.GonzalezAlberquilla@arm.com /** Zero the container. */ 29112108SRekai.GonzalezAlberquilla@arm.com void zero() { memset(container.data(), 0, SIZE); } 29212108SRekai.GonzalezAlberquilla@arm.com 29312108SRekai.GonzalezAlberquilla@arm.com /** Assignment operators. */ 29412108SRekai.GonzalezAlberquilla@arm.com /** @{ */ 29512108SRekai.GonzalezAlberquilla@arm.com /** From VecRegContainer */ 29612108SRekai.GonzalezAlberquilla@arm.com MyClass& operator=(const MyClass& that) 29712108SRekai.GonzalezAlberquilla@arm.com { 29812108SRekai.GonzalezAlberquilla@arm.com if (&that == this) 29912108SRekai.GonzalezAlberquilla@arm.com return *this; 30012108SRekai.GonzalezAlberquilla@arm.com memcpy(container.data(), that.container.data(), SIZE); 30112108SRekai.GonzalezAlberquilla@arm.com return *this; 30212108SRekai.GonzalezAlberquilla@arm.com } 30312108SRekai.GonzalezAlberquilla@arm.com 30412108SRekai.GonzalezAlberquilla@arm.com /** From appropriately sized uint8_t[]. */ 30512108SRekai.GonzalezAlberquilla@arm.com MyClass& operator=(const Container& that) 30612108SRekai.GonzalezAlberquilla@arm.com { 30712108SRekai.GonzalezAlberquilla@arm.com std::memcpy(container.data(), that.data(), SIZE); 30812108SRekai.GonzalezAlberquilla@arm.com return *this; 30912108SRekai.GonzalezAlberquilla@arm.com } 31012108SRekai.GonzalezAlberquilla@arm.com 31112108SRekai.GonzalezAlberquilla@arm.com /** From vector<uint8_t>. 31212108SRekai.GonzalezAlberquilla@arm.com * This is required for de-serialisation. 31312108SRekai.GonzalezAlberquilla@arm.com * */ 31412108SRekai.GonzalezAlberquilla@arm.com MyClass& operator=(const std::vector<uint8_t>& that) 31512108SRekai.GonzalezAlberquilla@arm.com { 31612108SRekai.GonzalezAlberquilla@arm.com assert(that.size() >= SIZE); 31712108SRekai.GonzalezAlberquilla@arm.com std::memcpy(container.data(), that.data(), SIZE); 31812108SRekai.GonzalezAlberquilla@arm.com return *this; 31912108SRekai.GonzalezAlberquilla@arm.com } 32012108SRekai.GonzalezAlberquilla@arm.com /** @} */ 32112108SRekai.GonzalezAlberquilla@arm.com 32212108SRekai.GonzalezAlberquilla@arm.com /** Copy the contents into the input buffer. */ 32312108SRekai.GonzalezAlberquilla@arm.com /** @{ */ 32412108SRekai.GonzalezAlberquilla@arm.com /** To appropriately sized uint8_t[] */ 32512108SRekai.GonzalezAlberquilla@arm.com void copyTo(Container& dst) const 32612108SRekai.GonzalezAlberquilla@arm.com { 32712108SRekai.GonzalezAlberquilla@arm.com std::memcpy(dst.data(), container.data(), SIZE); 32812108SRekai.GonzalezAlberquilla@arm.com } 32912108SRekai.GonzalezAlberquilla@arm.com 33012108SRekai.GonzalezAlberquilla@arm.com /** To vector<uint8_t> 33112108SRekai.GonzalezAlberquilla@arm.com * This is required for serialisation. 33212108SRekai.GonzalezAlberquilla@arm.com * */ 33312108SRekai.GonzalezAlberquilla@arm.com void copyTo(std::vector<uint8_t>& dst) const 33412108SRekai.GonzalezAlberquilla@arm.com { 33512108SRekai.GonzalezAlberquilla@arm.com dst.resize(SIZE); 33612108SRekai.GonzalezAlberquilla@arm.com std::memcpy(dst.data(), container.data(), SIZE); 33712108SRekai.GonzalezAlberquilla@arm.com } 33812108SRekai.GonzalezAlberquilla@arm.com /** @} */ 33912108SRekai.GonzalezAlberquilla@arm.com 34012108SRekai.GonzalezAlberquilla@arm.com /** Equality operator. 34112108SRekai.GonzalezAlberquilla@arm.com * Required to compare thread contexts. 34212108SRekai.GonzalezAlberquilla@arm.com */ 34312108SRekai.GonzalezAlberquilla@arm.com template<size_t S2> 34412108SRekai.GonzalezAlberquilla@arm.com inline bool 34512108SRekai.GonzalezAlberquilla@arm.com operator==(const VecRegContainer<S2>& that) const 34612108SRekai.GonzalezAlberquilla@arm.com { 34712108SRekai.GonzalezAlberquilla@arm.com return SIZE == S2 && 34812108SRekai.GonzalezAlberquilla@arm.com !memcmp(container.data(), that.container.data(), SIZE); 34912108SRekai.GonzalezAlberquilla@arm.com } 35012108SRekai.GonzalezAlberquilla@arm.com /** Inequality operator. 35112108SRekai.GonzalezAlberquilla@arm.com * Required to compare thread contexts. 35212108SRekai.GonzalezAlberquilla@arm.com */ 35312108SRekai.GonzalezAlberquilla@arm.com template<size_t S2> 35412108SRekai.GonzalezAlberquilla@arm.com bool 35512108SRekai.GonzalezAlberquilla@arm.com operator!=(const VecRegContainer<S2>& that) const 35612108SRekai.GonzalezAlberquilla@arm.com { 35712108SRekai.GonzalezAlberquilla@arm.com return !operator==(that); 35812108SRekai.GonzalezAlberquilla@arm.com } 35912108SRekai.GonzalezAlberquilla@arm.com 36012108SRekai.GonzalezAlberquilla@arm.com const std::string print() const { return csprintf("%s", *this); } 36112108SRekai.GonzalezAlberquilla@arm.com /** Get pointer to bytes. */ 36212108SRekai.GonzalezAlberquilla@arm.com template <typename Ret> 36312108SRekai.GonzalezAlberquilla@arm.com const Ret* raw_ptr() const { return (const Ret*)container.data(); } 36412108SRekai.GonzalezAlberquilla@arm.com 36512108SRekai.GonzalezAlberquilla@arm.com template <typename Ret> 36612108SRekai.GonzalezAlberquilla@arm.com Ret* raw_ptr() { return (Ret*)container.data(); } 36712108SRekai.GonzalezAlberquilla@arm.com 36812108SRekai.GonzalezAlberquilla@arm.com /** 36912108SRekai.GonzalezAlberquilla@arm.com * View interposers. 37012108SRekai.GonzalezAlberquilla@arm.com * Create a view of this container as a vector of VecElems with an 37112108SRekai.GonzalezAlberquilla@arm.com * optional amount of elements. If the amount of elements is provided, 37212108SRekai.GonzalezAlberquilla@arm.com * the size of the container is checked, to test bounds. If it is not 37312108SRekai.GonzalezAlberquilla@arm.com * provided, the length is inferred from the container size and the 37412108SRekai.GonzalezAlberquilla@arm.com * element size. 37512108SRekai.GonzalezAlberquilla@arm.com * @tparam VecElem Type of each element of the vector for the view. 37612108SRekai.GonzalezAlberquilla@arm.com * @tparam NumElem Amount of elements in the view. 37712108SRekai.GonzalezAlberquilla@arm.com */ 37812108SRekai.GonzalezAlberquilla@arm.com /** @{ */ 37912108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem, size_t NumElems = SIZE/sizeof(VecElem)> 38012108SRekai.GonzalezAlberquilla@arm.com VecRegT<VecElem, NumElems, true> as() const 38112108SRekai.GonzalezAlberquilla@arm.com { 38212108SRekai.GonzalezAlberquilla@arm.com static_assert(SIZE % sizeof(VecElem) == 0, 38312108SRekai.GonzalezAlberquilla@arm.com "VecElem does not evenly divide the register size"); 38412108SRekai.GonzalezAlberquilla@arm.com static_assert(sizeof(VecElem) * NumElems <= SIZE, 38512108SRekai.GonzalezAlberquilla@arm.com "Viewing VecReg as something bigger than it is"); 38612108SRekai.GonzalezAlberquilla@arm.com return VecRegT<VecElem, NumElems, true>(*this); 38712108SRekai.GonzalezAlberquilla@arm.com } 38812108SRekai.GonzalezAlberquilla@arm.com 38912108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem, size_t NumElems = SIZE/sizeof(VecElem)> 39012108SRekai.GonzalezAlberquilla@arm.com VecRegT<VecElem, NumElems, false> as() 39112108SRekai.GonzalezAlberquilla@arm.com { 39212108SRekai.GonzalezAlberquilla@arm.com static_assert(SIZE % sizeof(VecElem) == 0, 39312108SRekai.GonzalezAlberquilla@arm.com "VecElem does not evenly divide the register size"); 39412108SRekai.GonzalezAlberquilla@arm.com static_assert(sizeof(VecElem) * NumElems <= SIZE, 39512108SRekai.GonzalezAlberquilla@arm.com "Viewing VecReg as something bigger than it is"); 39612108SRekai.GonzalezAlberquilla@arm.com return VecRegT<VecElem, NumElems, false>(*this); 39712108SRekai.GonzalezAlberquilla@arm.com } 39812108SRekai.GonzalezAlberquilla@arm.com 39912108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem, int LaneIdx> 40012108SRekai.GonzalezAlberquilla@arm.com VecLaneT<VecElem, false> laneView(); 40112108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem, int LaneIdx> 40212108SRekai.GonzalezAlberquilla@arm.com VecLaneT<VecElem, true> laneView() const; 40312108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem> 40412108SRekai.GonzalezAlberquilla@arm.com VecLaneT<VecElem, false> laneView(int laneIdx); 40512108SRekai.GonzalezAlberquilla@arm.com template <typename VecElem> 40612108SRekai.GonzalezAlberquilla@arm.com VecLaneT<VecElem, true> laneView(int laneIdx) const; 40712108SRekai.GonzalezAlberquilla@arm.com /** @} */ 40812108SRekai.GonzalezAlberquilla@arm.com /** 40912108SRekai.GonzalezAlberquilla@arm.com * Output operator. 41012108SRekai.GonzalezAlberquilla@arm.com * Used for serialization. 41112108SRekai.GonzalezAlberquilla@arm.com */ 41212108SRekai.GonzalezAlberquilla@arm.com friend std::ostream& operator<<(std::ostream& os, const MyClass& v) 41312108SRekai.GonzalezAlberquilla@arm.com { 41412108SRekai.GonzalezAlberquilla@arm.com for (auto& b: v.container) { 41512108SRekai.GonzalezAlberquilla@arm.com os << csprintf("%02x", b); 41612108SRekai.GonzalezAlberquilla@arm.com } 41712108SRekai.GonzalezAlberquilla@arm.com return os; 41812108SRekai.GonzalezAlberquilla@arm.com } 41912108SRekai.GonzalezAlberquilla@arm.com}; 42012108SRekai.GonzalezAlberquilla@arm.com 42112108SRekai.GonzalezAlberquilla@arm.com/** We define an auxiliary abstraction for LaneData. The ISA should care 42212108SRekai.GonzalezAlberquilla@arm.com * about the semantics of a, e.g., 32bit element, treating it as a signed or 42312108SRekai.GonzalezAlberquilla@arm.com * unsigned int, or a float depending on the semantics of a particular 42412108SRekai.GonzalezAlberquilla@arm.com * instruction. On the other hand, the cpu model should only care about it 42512108SRekai.GonzalezAlberquilla@arm.com * being a 32-bit value. */ 42612108SRekai.GonzalezAlberquilla@arm.comenum class LaneSize 42712108SRekai.GonzalezAlberquilla@arm.com{ 42812108SRekai.GonzalezAlberquilla@arm.com Empty = 0, 42912108SRekai.GonzalezAlberquilla@arm.com Byte, 43012108SRekai.GonzalezAlberquilla@arm.com TwoByte, 43112108SRekai.GonzalezAlberquilla@arm.com FourByte, 43212108SRekai.GonzalezAlberquilla@arm.com EightByte, 43312108SRekai.GonzalezAlberquilla@arm.com}; 43412108SRekai.GonzalezAlberquilla@arm.com 43512108SRekai.GonzalezAlberquilla@arm.com/** LaneSize is an abstraction of a LS byte value for the execution and thread 43612108SRekai.GonzalezAlberquilla@arm.com * contexts to handle values just depending on its width. That way, the ISA 43712108SRekai.GonzalezAlberquilla@arm.com * can request, for example, the second 4 byte lane of register 5 to the model. 43812108SRekai.GonzalezAlberquilla@arm.com * The model serves that value, agnostic of the semantics of those bits. Then, 43912108SRekai.GonzalezAlberquilla@arm.com * it is up to the ISA to interpret those bits as a float, or as an uint. 44012108SRekai.GonzalezAlberquilla@arm.com * To maximize the utility, this class implements the assignment operator and 44112108SRekai.GonzalezAlberquilla@arm.com * the casting to equal-size types. 44212108SRekai.GonzalezAlberquilla@arm.com * As opposed to a RegLaneT, LaneData is not 'backed' by a VecRegContainer. 44312108SRekai.GonzalezAlberquilla@arm.com * The idea is: 44412108SRekai.GonzalezAlberquilla@arm.com * When data is passed and is susceptible to being copied, use LaneData, as 44512108SRekai.GonzalezAlberquilla@arm.com * copying the primitive type is build on is cheap. 44612108SRekai.GonzalezAlberquilla@arm.com * When data is passed as references (const or not), use RegLaneT, as all 44712108SRekai.GonzalezAlberquilla@arm.com * operations happen 'in place', avoiding any copies (no copies is always 44812108SRekai.GonzalezAlberquilla@arm.com * cheaper than cheap copies), especially when things are inlined, and 44912108SRekai.GonzalezAlberquilla@arm.com * references are not explicitly passed. 45012108SRekai.GonzalezAlberquilla@arm.com */ 45112108SRekai.GonzalezAlberquilla@arm.comtemplate <LaneSize LS> 45212108SRekai.GonzalezAlberquilla@arm.comclass LaneData 45312108SRekai.GonzalezAlberquilla@arm.com{ 45412108SRekai.GonzalezAlberquilla@arm.com public: 45512108SRekai.GonzalezAlberquilla@arm.com /** Alias to the native type of the appropriate size. */ 45612108SRekai.GonzalezAlberquilla@arm.com using UnderlyingType = 45712108SRekai.GonzalezAlberquilla@arm.com typename std::conditional<LS == LaneSize::EightByte, uint64_t, 45812108SRekai.GonzalezAlberquilla@arm.com typename std::conditional<LS == LaneSize::FourByte, uint32_t, 45912108SRekai.GonzalezAlberquilla@arm.com typename std::conditional<LS == LaneSize::TwoByte, uint16_t, 46012108SRekai.GonzalezAlberquilla@arm.com typename std::conditional<LS == LaneSize::Byte, uint8_t, 46112108SRekai.GonzalezAlberquilla@arm.com void>::type 46212108SRekai.GonzalezAlberquilla@arm.com >::type 46312108SRekai.GonzalezAlberquilla@arm.com >::type 46412108SRekai.GonzalezAlberquilla@arm.com >::type; 46512108SRekai.GonzalezAlberquilla@arm.com private: 46612108SRekai.GonzalezAlberquilla@arm.com static constexpr auto ByteSz = sizeof(UnderlyingType); 46712108SRekai.GonzalezAlberquilla@arm.com UnderlyingType _val; 46812108SRekai.GonzalezAlberquilla@arm.com using MyClass = LaneData<LS>; 46912108SRekai.GonzalezAlberquilla@arm.com 47012108SRekai.GonzalezAlberquilla@arm.com public: 47112108SRekai.GonzalezAlberquilla@arm.com template <typename T> explicit 47212108SRekai.GonzalezAlberquilla@arm.com LaneData(typename std::enable_if<sizeof(T) == ByteSz, const T&>::type t) 47312108SRekai.GonzalezAlberquilla@arm.com : _val(t) {} 47412108SRekai.GonzalezAlberquilla@arm.com 47512108SRekai.GonzalezAlberquilla@arm.com template <typename T> 47612108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<sizeof(T) == ByteSz, MyClass&>::type 47712108SRekai.GonzalezAlberquilla@arm.com operator=(const T& that) 47812108SRekai.GonzalezAlberquilla@arm.com { 47912108SRekai.GonzalezAlberquilla@arm.com _val = that; 48012108SRekai.GonzalezAlberquilla@arm.com return *this; 48112108SRekai.GonzalezAlberquilla@arm.com } 48212108SRekai.GonzalezAlberquilla@arm.com template<typename T, 48312108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<sizeof(T) == ByteSz, int>::type I = 0> 48412108SRekai.GonzalezAlberquilla@arm.com operator T() const { 48512108SRekai.GonzalezAlberquilla@arm.com return *static_cast<const T*>(&_val); 48612108SRekai.GonzalezAlberquilla@arm.com } 48712108SRekai.GonzalezAlberquilla@arm.com}; 48812108SRekai.GonzalezAlberquilla@arm.com 48912108SRekai.GonzalezAlberquilla@arm.com/** Output operator overload for LaneData<Size>. */ 49012108SRekai.GonzalezAlberquilla@arm.comtemplate <LaneSize LS> 49112108SRekai.GonzalezAlberquilla@arm.cominline std::ostream& 49212108SRekai.GonzalezAlberquilla@arm.comoperator<<(std::ostream& os, const LaneData<LS>& d) 49312108SRekai.GonzalezAlberquilla@arm.com{ 49412108SRekai.GonzalezAlberquilla@arm.com return os << static_cast<typename LaneData<LS>::UnderlyingType>(d); 49512108SRekai.GonzalezAlberquilla@arm.com} 49612108SRekai.GonzalezAlberquilla@arm.com 49712108SRekai.GonzalezAlberquilla@arm.com/** Vector Lane abstraction 49812108SRekai.GonzalezAlberquilla@arm.com * Another view of a container. This time only a partial part of it is exposed. 49912108SRekai.GonzalezAlberquilla@arm.com * @tparam VecElem Type of each element of the vector. 50012108SRekai.GonzalezAlberquilla@arm.com * @tparam Const Indicate if the underlying container can be modified through 50112108SRekai.GonzalezAlberquilla@arm.com * the view. 50212108SRekai.GonzalezAlberquilla@arm.com */ 50312108SRekai.GonzalezAlberquilla@arm.com/** @{ */ 50412108SRekai.GonzalezAlberquilla@arm.com/* General */ 50512108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem, bool Const> 50612108SRekai.GonzalezAlberquilla@arm.comclass VecLaneT 50712108SRekai.GonzalezAlberquilla@arm.com{ 50812108SRekai.GonzalezAlberquilla@arm.com public: 50912108SRekai.GonzalezAlberquilla@arm.com /** VecRegContainer friendship to access private VecLaneT constructors. 51012108SRekai.GonzalezAlberquilla@arm.com * Only VecRegContainers can build VecLanes. 51112108SRekai.GonzalezAlberquilla@arm.com */ 51212108SRekai.GonzalezAlberquilla@arm.com /** @{ */ 51312108SRekai.GonzalezAlberquilla@arm.com friend VecLaneT<VecElem, !Const>; 51412108SRekai.GonzalezAlberquilla@arm.com 51512108SRekai.GonzalezAlberquilla@arm.com /*template <size_t Sz> 51612108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer;*/ 51712108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer<8>; 51812108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer<16>; 51912108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer<32>; 52012108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer<64>; 52112108SRekai.GonzalezAlberquilla@arm.com friend class VecRegContainer<128>; 52212108SRekai.GonzalezAlberquilla@arm.com 52312108SRekai.GonzalezAlberquilla@arm.com /** My type alias. */ 52412108SRekai.GonzalezAlberquilla@arm.com using MyClass = VecLaneT<VecElem, Const>; 52512108SRekai.GonzalezAlberquilla@arm.com 52612108SRekai.GonzalezAlberquilla@arm.com private: 52712108SRekai.GonzalezAlberquilla@arm.com using Cont = typename std::conditional<Const, 52812108SRekai.GonzalezAlberquilla@arm.com const VecElem, 52912108SRekai.GonzalezAlberquilla@arm.com VecElem>::type; 53012108SRekai.GonzalezAlberquilla@arm.com static_assert(!std::is_const<VecElem>::value || Const, 53112108SRekai.GonzalezAlberquilla@arm.com "Asked for non-const lane of const type!"); 53212108SRekai.GonzalezAlberquilla@arm.com static_assert(std::is_integral<VecElem>::value, 53312108SRekai.GonzalezAlberquilla@arm.com "VecElem type is not integral!"); 53412108SRekai.GonzalezAlberquilla@arm.com /** Reference to data. */ 53512108SRekai.GonzalezAlberquilla@arm.com Cont& container; 53612108SRekai.GonzalezAlberquilla@arm.com 53712108SRekai.GonzalezAlberquilla@arm.com /** Constructor */ 53812108SRekai.GonzalezAlberquilla@arm.com VecLaneT(Cont& cont) : container(cont) { } 53912108SRekai.GonzalezAlberquilla@arm.com 54012108SRekai.GonzalezAlberquilla@arm.com public: 54112108SRekai.GonzalezAlberquilla@arm.com /** Assignment operators. 54212108SRekai.GonzalezAlberquilla@arm.com * Assignment operators are only enabled if the underlying container is 54312108SRekai.GonzalezAlberquilla@arm.com * non-constant. 54412108SRekai.GonzalezAlberquilla@arm.com */ 54512108SRekai.GonzalezAlberquilla@arm.com /** @{ */ 54612108SRekai.GonzalezAlberquilla@arm.com template <bool Assignable = !Const> 54712108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<Assignable, MyClass&>::type 54812108SRekai.GonzalezAlberquilla@arm.com operator=(const VecElem& that) { 54912108SRekai.GonzalezAlberquilla@arm.com container = that; 55012108SRekai.GonzalezAlberquilla@arm.com return *this; 55112108SRekai.GonzalezAlberquilla@arm.com } 55212108SRekai.GonzalezAlberquilla@arm.com /** 55312108SRekai.GonzalezAlberquilla@arm.com * Generic. 55412108SRekai.GonzalezAlberquilla@arm.com * Generic bitwise assignment. Narrowing and widening assignemnts are 55512108SRekai.GonzalezAlberquilla@arm.com * not allowed, pre-treatment of the rhs is required to conform. 55612108SRekai.GonzalezAlberquilla@arm.com */ 55712108SRekai.GonzalezAlberquilla@arm.com template <bool Assignable = !Const, typename T> 55812108SRekai.GonzalezAlberquilla@arm.com typename std::enable_if<Assignable, MyClass&>::type 55912108SRekai.GonzalezAlberquilla@arm.com operator=(const T& that) { 56012108SRekai.GonzalezAlberquilla@arm.com static_assert(sizeof(T) >= sizeof(VecElem), 56112108SRekai.GonzalezAlberquilla@arm.com "Attempt to perform widening bitwise copy."); 56212108SRekai.GonzalezAlberquilla@arm.com static_assert(sizeof(T) <= sizeof(VecElem), 56312108SRekai.GonzalezAlberquilla@arm.com "Attempt to perform narrowing bitwise copy."); 56412108SRekai.GonzalezAlberquilla@arm.com container = static_cast<VecElem>(that); 56512108SRekai.GonzalezAlberquilla@arm.com return *this; 56612108SRekai.GonzalezAlberquilla@arm.com } 56712108SRekai.GonzalezAlberquilla@arm.com /** @} */ 56812108SRekai.GonzalezAlberquilla@arm.com /** Cast to vecElem. */ 56912108SRekai.GonzalezAlberquilla@arm.com operator VecElem() const { return container; } 57012108SRekai.GonzalezAlberquilla@arm.com 57112108SRekai.GonzalezAlberquilla@arm.com /** Constification. */ 57212108SRekai.GonzalezAlberquilla@arm.com template <bool Cond = !Const, typename std::enable_if<Cond, int>::type = 0> 57312108SRekai.GonzalezAlberquilla@arm.com operator VecLaneT<typename std::enable_if<Cond, VecElem>::type, true>() 57412108SRekai.GonzalezAlberquilla@arm.com { 57512108SRekai.GonzalezAlberquilla@arm.com return VecLaneT<VecElem, true>(container); 57612108SRekai.GonzalezAlberquilla@arm.com } 57712108SRekai.GonzalezAlberquilla@arm.com}; 57812108SRekai.GonzalezAlberquilla@arm.com 57912108SRekai.GonzalezAlberquilla@arm.comnamespace std { 58012108SRekai.GonzalezAlberquilla@arm.com template<typename T, bool Const> 58112108SRekai.GonzalezAlberquilla@arm.com struct add_const<VecLaneT<T, Const>> { typedef VecLaneT<T, true> type; }; 58212108SRekai.GonzalezAlberquilla@arm.com} 58312108SRekai.GonzalezAlberquilla@arm.com 58412108SRekai.GonzalezAlberquilla@arm.com/** View as the Nth lane of type VecElem. */ 58512108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 58612108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem, int LaneIdx> 58712108SRekai.GonzalezAlberquilla@arm.comVecLaneT<VecElem, false> 58812108SRekai.GonzalezAlberquilla@arm.comVecRegContainer<Sz>::laneView() 58912108SRekai.GonzalezAlberquilla@arm.com{ 59012108SRekai.GonzalezAlberquilla@arm.com return VecLaneT<VecElem, false>(as<VecElem>()[LaneIdx]); 59112108SRekai.GonzalezAlberquilla@arm.com} 59212108SRekai.GonzalezAlberquilla@arm.com 59312108SRekai.GonzalezAlberquilla@arm.com/** View as the const Nth lane of type VecElem. */ 59412108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 59512108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem, int LaneIdx> 59612108SRekai.GonzalezAlberquilla@arm.comVecLaneT<VecElem, true> 59712108SRekai.GonzalezAlberquilla@arm.comVecRegContainer<Sz>::laneView() const 59812108SRekai.GonzalezAlberquilla@arm.com{ 59912108SRekai.GonzalezAlberquilla@arm.com return VecLaneT<VecElem, true>(as<VecElem>()[LaneIdx]); 60012108SRekai.GonzalezAlberquilla@arm.com} 60112108SRekai.GonzalezAlberquilla@arm.com 60212108SRekai.GonzalezAlberquilla@arm.com/** View as the Nth lane of type VecElem. */ 60312108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 60412108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem> 60512108SRekai.GonzalezAlberquilla@arm.comVecLaneT<VecElem, false> 60612108SRekai.GonzalezAlberquilla@arm.comVecRegContainer<Sz>::laneView(int laneIdx) 60712108SRekai.GonzalezAlberquilla@arm.com{ 60812108SRekai.GonzalezAlberquilla@arm.com return VecLaneT<VecElem, false>(as<VecElem>()[laneIdx]); 60912108SRekai.GonzalezAlberquilla@arm.com} 61012108SRekai.GonzalezAlberquilla@arm.com 61112108SRekai.GonzalezAlberquilla@arm.com/** View as the const Nth lane of type VecElem. */ 61212108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 61312108SRekai.GonzalezAlberquilla@arm.comtemplate <typename VecElem> 61412108SRekai.GonzalezAlberquilla@arm.comVecLaneT<VecElem, true> 61512108SRekai.GonzalezAlberquilla@arm.comVecRegContainer<Sz>::laneView(int laneIdx) const 61612108SRekai.GonzalezAlberquilla@arm.com{ 61712108SRekai.GonzalezAlberquilla@arm.com return VecLaneT<VecElem, true>(as<VecElem>()[laneIdx]); 61812108SRekai.GonzalezAlberquilla@arm.com} 61912108SRekai.GonzalezAlberquilla@arm.com 62012108SRekai.GonzalezAlberquilla@arm.comusing VecLane8 = VecLaneT<uint8_t, false>; 62112108SRekai.GonzalezAlberquilla@arm.comusing VecLane16 = VecLaneT<uint16_t, false>; 62212108SRekai.GonzalezAlberquilla@arm.comusing VecLane32 = VecLaneT<uint32_t, false>; 62312108SRekai.GonzalezAlberquilla@arm.comusing VecLane64 = VecLaneT<uint64_t, false>; 62412108SRekai.GonzalezAlberquilla@arm.com 62512108SRekai.GonzalezAlberquilla@arm.comusing ConstVecLane8 = VecLaneT<uint8_t, true>; 62612108SRekai.GonzalezAlberquilla@arm.comusing ConstVecLane16 = VecLaneT<uint16_t, true>; 62712108SRekai.GonzalezAlberquilla@arm.comusing ConstVecLane32 = VecLaneT<uint32_t, true>; 62812108SRekai.GonzalezAlberquilla@arm.comusing ConstVecLane64 = VecLaneT<uint64_t, true>; 62912108SRekai.GonzalezAlberquilla@arm.com 63012108SRekai.GonzalezAlberquilla@arm.com/** 63112108SRekai.GonzalezAlberquilla@arm.com * Calls required for serialization/deserialization 63212108SRekai.GonzalezAlberquilla@arm.com */ 63312108SRekai.GonzalezAlberquilla@arm.com/** @{ */ 63412108SRekai.GonzalezAlberquilla@arm.comtemplate <size_t Sz> 63512108SRekai.GonzalezAlberquilla@arm.cominline bool 63612108SRekai.GonzalezAlberquilla@arm.comto_number(const std::string& value, VecRegContainer<Sz>& v) 63712108SRekai.GonzalezAlberquilla@arm.com{ 63812108SRekai.GonzalezAlberquilla@arm.com int i = 0; 63912108SRekai.GonzalezAlberquilla@arm.com while (i < Sz) { 64012108SRekai.GonzalezAlberquilla@arm.com std::string byte = value.substr(i<<1, 2); 64112108SRekai.GonzalezAlberquilla@arm.com v.template raw_ptr<uint8_t>()[i] = stoul(byte, 0, 16); 64212108SRekai.GonzalezAlberquilla@arm.com i++; 64312108SRekai.GonzalezAlberquilla@arm.com } 64412108SRekai.GonzalezAlberquilla@arm.com return true; 64512108SRekai.GonzalezAlberquilla@arm.com} 64612108SRekai.GonzalezAlberquilla@arm.com/** @} */ 64712108SRekai.GonzalezAlberquilla@arm.com 64812108SRekai.GonzalezAlberquilla@arm.com#endif /* __ARCH_GENERIC_VEC_REG_HH__ */ 649