/* * Copyright 2014 Google, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Gabe Black */ #include #include #include "base/bitunion.hh" #include "base/cprintf.hh" #include "unittest/unittest.hh" using namespace std; using UnitTest::setCase; namespace { BitUnion64(SixtyFour) Bitfield<39, 32> byte5; Bitfield<2> bit2; BitfieldRO<39, 32> byte5RO; BitfieldWO<39, 32> byte5WO; SubBitUnion(byte6, 47, 40) Bitfield<43, 42> bits43To42; Bitfield<41> bit41; SignedBitfield<41> bit41Signed; EndSubBitUnion(byte6) SignedBitfield<47, 40> byte6Signed; SignedBitfieldRO<47, 40> byte6SignedRO; SignedBitfieldWO<47, 40> byte6SignedWO; EndBitUnion(SixtyFour) BitUnion64(EmptySixtyFour) EndBitUnion(EmptySixtyFour) BitUnion32(EmptyThirtyTwo) EndBitUnion(EmptyThirtyTwo) BitUnion16(EmptySixteen) EndBitUnion(EmptySixteen) BitUnion8(EmptyEight) EndBitUnion(EmptyEight) struct ContainingStruct { BitUnion64(Contained) Bitfield<63, 60> topNibble; EndBitUnion(Contained) Contained contained; }; uint64_t containingFunc(uint64_t init_val, uint64_t fieldVal) { BitUnion32(Contained) Bitfield<16, 15> field; EndBitUnion(Contained) Contained contained = init_val; contained.field = fieldVal; return contained; } } // anonymous namespace // Declare these as global so g++ doesn't ignore them. Initialize them in // various ways. EmptySixtyFour emptySixtyFour = 0; EmptyThirtyTwo emptyThirtyTwo; EmptySixteen emptySixteen; EmptyEight emptyEight(0); int main() { SixtyFour sixtyFour = 0; setCase("normal bitfield"); EXPECT_EQ(sixtyFour.byte5, 0); sixtyFour.byte5 = 0xff; EXPECT_EQ(sixtyFour, 0xff00000000); sixtyFour.byte5 = 0xfff; EXPECT_EQ(sixtyFour, 0xff00000000); EXPECT_EQ(sixtyFour.byte5, 0xff); sixtyFour = 0; setCase("single bitfield"); EXPECT_EQ(sixtyFour.bit2, 0); sixtyFour.bit2 = 0x1; EXPECT_EQ(sixtyFour, 0x4); EXPECT_EQ(sixtyFour.bit2, 0x1); sixtyFour = 0; setCase("read only bitfield"); EXPECT_EQ(sixtyFour.byte5RO, 0); sixtyFour.byte5 = 0xff; EXPECT_EQ(sixtyFour.byte5RO, 0xff); sixtyFour = 0; setCase("write only bitfield"); sixtyFour.byte5WO = 0xff; EXPECT_EQ(sixtyFour, 0xff00000000); sixtyFour = 0; setCase("sub bitunions and their bitfields"); EXPECT_EQ(sixtyFour.byte6.bit41, 0); sixtyFour.byte6 = 0x2; EXPECT_EQ(sixtyFour.byte6.bit41, 1); sixtyFour.byte6.bits43To42 = 0x3; EXPECT_EQ(sixtyFour.byte6, 0xe); sixtyFour.byte6 = 0xff; sixtyFour.byte6.bit41 = 0; EXPECT_EQ(sixtyFour, 0xfd0000000000); sixtyFour = 0; setCase("normal, read only, and write only signed bitfields"); sixtyFour.byte6 = 0xff; EXPECT_EQ(sixtyFour.byte6Signed, -1); EXPECT_EQ(sixtyFour.byte6SignedRO, -1); sixtyFour.byte6SignedWO = 0; EXPECT_EQ(sixtyFour.byte6Signed, 0); EXPECT_EQ(sixtyFour.byte6SignedRO, 0); EXPECT_EQ(sixtyFour.byte6, 0); sixtyFour = 0; setCase("bitunion declared inside a struct"); ContainingStruct containing; containing.contained = 0; containing.contained.topNibble = 0xd; EXPECT_EQ(containing.contained, 0xd000000000000000); setCase("bitunion declared inside a function"); EXPECT_EQ(containingFunc(0xfffff, 0), 0xe7fff); setCase("assigning bitfields to other bitfields"); SixtyFour otherSixtyFour = 0; sixtyFour.bit2 = 1; otherSixtyFour.byte6.bit41 = sixtyFour.bit2; EXPECT_EQ(otherSixtyFour, 0x20000000000); otherSixtyFour.bit2 = sixtyFour.bit2; EXPECT_EQ(otherSixtyFour, 0x20000000004); setCase("bitunion operators"); sixtyFour = 0; otherSixtyFour = 0x4; sixtyFour = otherSixtyFour; EXPECT_EQ(sixtyFour, 0x4); sixtyFour = 0; EXPECT_TRUE(sixtyFour < otherSixtyFour); EXPECT_TRUE(otherSixtyFour > sixtyFour); EXPECT_TRUE(sixtyFour != otherSixtyFour); sixtyFour = otherSixtyFour; EXPECT_TRUE(sixtyFour == otherSixtyFour); return UnitTest::printResults(); }