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