1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 | #include <iostream>
#include <sstream>
#include <stdexcept>
#include "expr.hpp"
#include "exprwrapper.hpp"
#include "instrfmt.hpp"
namespace ulmdoc {
InstrFmt::InstrFmt(std::vector<ExprWrapper> fmtField)
: sym(fmtField.size())
, size(fmtField.size())
, offset(fmtField.size())
, type(fmtField.size())
{
for (std::size_t i = 0; i < fmtField.size(); ++i) {
auto &repr = fmtField[i].exprPtr->repr;
if (!std::holds_alternative<Expr::TypedBitPattern>(repr)) {
throw std::logic_error("field of an instruction format has to be "
"of type Expr::TypedBitPattern");
}
auto &t = std::get<Expr::TypedBitPattern>(repr);
sym[i] = t.sym;
size[i] = t.numBits;
offset[i] = (i == 0 ? 32 : offset[i - 1]) - size[i];
type[i] = t.bitPatternType;
}
}
std::string
InstrFmt::tikz(std::size_t opCode)
{
std::string str = tikzHeader();
for (std::size_t i = 0; i < sym.size(); ++i) {
std::ostringstream label;
if (i == 0) {
if (size[i] % 4 == 0) {
label << "0x";
label.width(size[i]/4);
label.fill('0');
label << std::hex << std::uppercase << opCode;
} else {
for (std::size_t j = size[i]; j-- > 0;) {
label << ((opCode & (1 << j)) >> j);
}
}
} else {
label << sym[i];
if (type[i] == Expr::JUMP_OFFSET) {
label << "\\gg 2";
}
}
str += tikzCell(size[i], offset[i], label.str());
}
if (offset.back() != 0) {
str += tikzCell(offset.back(), 0, "", false);
}
return str + tikzFooter();
}
std::string
InstrFmt::tikzHeader() const
{
std::ostringstream ss;
ss << "\\[\\begin{tikzpicture}[scale=0.6]" << std::endl;
return ss.str();
}
std::string
InstrFmt::tikzFooter() const
{
std::ostringstream ss;
ss << "\\end{tikzpicture}\\]" << std::endl;
return ss.str();
}
std::string
InstrFmt::tikzCell(std::size_t numBits, std::size_t offset,
std::string label, bool used) const
{
std::ostringstream ss;
ss << "\\filldraw[fill=" << (used ? "white" : "gray!30") << "]" << std::endl
<< " ({ " << scale * (32 - offset - numBits) << "}, {1}) --" << std::endl
<< " ({ " << scale * (32 - offset - numBits) << "}, {0}) --" << std::endl
<< " ({ " << scale * (32 - offset) << "}, {0}) --" << std::endl
<< " ({ " << scale * (32 - offset) << "}, {1}) --" << std::endl
<< " cycle;" << std::endl;
ss << "\\draw ({" << scale * (32 - offset - numBits / 2.)
<< "}, {0.5}) node {" << label << "};" << std::endl;
ss << tikzCellOffset(offset);
if (offset + numBits == 32) {
ss << tikzCellOffset(32);
}
return ss.str();
}
std::string
InstrFmt::tikzCellOffset(std::size_t offset) const
{
std::ostringstream ss;
ss << "\\draw ({" << scale * (32 - offset) << "}, {1}) --" << std::endl
<< " ({" << scale * (32 - offset) << "}, {1.2}) node[above] {" << offset
<< "};" << std::endl;
return ss.str();
}
} // namespace ulmdoc
|