1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "InstEncoder.hpp"
10 #include "../BitProcessor.hpp"
11 
12 #include <sstream>
13 
14 // dummy symbol to avoid LNK4221 warning
15 
16 using namespace iga;
17 
18 #ifdef IGA_VALIDATE_BITS
reportFieldOverlap(const Fragment & fr)19 void InstEncoder::reportFieldOverlap(const Fragment &fr)
20 {
21     std::stringstream ss;
22     ss << "INTERNAL ERROR: ";
23     ss << "instruction #" << state.instIndex <<
24         " [PC 0x" << std::hex << state.inst->getPC() << "]: " <<
25         fr.name << " overlaps with ";
26     // iterate the old fragments and find one that overlapped
27     for (const Fragment *of : state.fragmentsSet) {
28         if (of->overlaps(fr)) {
29             ss << of->name;
30             auto str = ss.str();
31             // std::cerr << "checkFieldOverlaps: " << str << "\n";
32             // IGA_ASSERT_FALSE(str.c_str());
33             errorT(str);
34             return;
35         }
36     }
37     ss << "another field (?)";
38     auto str = ss.str();
39     errorT(str);
40     // IGA_ASSERT_FALSE(str.c_str());
41 }
42 #endif
43 
encodeFieldBits(const Field & f,uint64_t val0)44 void InstEncoder::encodeFieldBits(const Field &f, uint64_t val0)
45 {
46 #ifndef IGA_VALIDATE_BITS
47     // bit-validation can't cut this corner
48     if (val0 == 0) {
49         // short circuit since we start with zeros
50         return;
51     }
52 #endif
53     uint64_t val = val0;
54     for (const Fragment &fr : f.fragments) {
55         if (fr.kind == Fragment::Kind::INVALID)
56             break;
57         const auto MASK = fr.getMask();
58         const auto fragValue = val & MASK;
59         switch (fr.kind) {
60         case Fragment::Kind::ENCODED:
61             bits->setBits(fr.offset, fr.length, fragValue);
62 #ifdef IGA_VALIDATE_BITS
63             if (state.dirty.getBits(fr.offset, fr.length)) {
64                 // some of these bits have already been set by some
65                 // other field; this demonstrates an internal error
66                 // in our encoding logic
67                 reportFieldOverlap(fr);
68             }
69             state.fragmentsSet.push_back(&fr);
70             state.dirty.setBits(fr.offset, fr.length, MASK);
71 #endif
72             break;
73         case Fragment::Kind::ZERO_WIRES:
74         case Fragment::Kind::ZERO_FILL:
75             if (fragValue != 0) {
76                 errorAtT(state.inst->getLoc(),
77                     fr.name, ": ", fmtHex(val0), ": field fragment must be zero");
78             }
79             break;
80         default:
81             IGA_ASSERT_FALSE("unreachable");
82         }
83         val >>= fr.length;
84     }
85 
86     if (val != 0) {
87         // value overflows the virtual encoding
88         errorAtT(state.inst->getLoc(),
89             f.name, ": ", fmtHex(val0), ": value is too large for field");
90     }
91 }
92