forked from Arakula/dasmfw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMemory.h
348 lines (322 loc) · 12.6 KB
/
Memory.h
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/***************************************************************************
* dasmfw -- Disassembler Framework *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
/*****************************************************************************/
/* Memory.h : definition for the memory classes */
/*****************************************************************************/
#ifndef __Memory_h_defined__
#define __Memory_h_defined__
#include "dasmfw.h"
#include "Label.h"
/*
Memory contents have some kinds of attributes:
a) the memory type (Code, Data, Const, BSS)
b) flag whether used or unused
c) if not code, the cell size (1, 2, 4, 8, 10, 16, 32, ...)
d) if not code, the cell type (signed int, unsigned int, float)
e) if not code (or data reference / constant in code),
the display format (binary, character, octal, decimal, hex)
*/
/*****************************************************************************/
/* TMemory : template for a vector with a start address */
/*****************************************************************************/
template<class T, class TType = uint8_t> class TMemory : public vector<T>
{
public:
TMemory(adr_t addrStart = 0, adr_t memSize = 0, TType newType = (TType)0)
: memType(newType)
{
label.SetAddress(addrStart);
if (memSize)
this->resize(static_cast<typename vector<T>::size_type>(memSize));
}
TMemory(TMemory const &org) : vector<T>(org)
{ DoCopy(org); }
TMemory &operator=(TMemory const &org)
{ return DoCopy(org); }
// Getters / Setters
void SetStart(adr_t addrStart = 0) { label.SetAddress(addrStart); }
adr_t GetStart() const { return label.GetAddress(); }
adr_t GetEnd() const { return GetStart() + vector<T>::size() - 1; }
string GetLabel() { return label.GetText(); }
bool SetLabel(string sNewText = "") { return label.SetText(sNewText); }
TType GetType() { return memType; }
void SetType(TType newType) { memType = newType; }
bool TypeMatches(TType chkType) { return memType == chkType; }
// vector specializations
typename vector<T>::const_reference at(typename vector<T>::size_type _Pos) const
{ return vector<T>::at(_Pos - GetStart()); }
typename vector<T>::reference at(typename vector<T>::size_type _Pos)
{ return vector<T>::at(_Pos - GetStart()); }
typename vector<T>::const_reference operator[](typename vector<T>::size_type _Pos) const
{ return at(_Pos); }
typename vector<T>::reference operator[](typename vector<T>::size_type _Pos)
{ return at(_Pos); }
protected:
Label label;
TType memType;
TMemory &DoCopy(TMemory const &org)
{
label = org.label;
memType = org.memType;
this->assign(org.begin(), org.end());
return *this;
}
};
/*****************************************************************************/
/* TMemoryArray : template for an array of disjunct vectors with start addr. */
/*****************************************************************************/
template<class T, class TType = uint8_t>
class TMemoryArray : public vector<TMemory<T, TType>>
{
public:
TMemoryArray() { ResetLast(); }
bool AddMemory(adr_t addrStart = 0, adr_t memSize = 0, TType memType = (TType)0, T *contents = NULL)
{
typename vector<TMemory<T, TType>>::iterator i;
if (memSize)
{
adr_t addrEnd = addrStart + memSize - 1;
// append to existing array, if possible
for (i = vector<TMemory<T, TType>>::begin(); i != vector<TMemory<T, TType>>::end(); i++)
{
if (i->TypeMatches(memType))
{
adr_t curStart = i->GetStart();
adr_t curEnd = i->GetEnd();
adr_t curSize = i->size();
// adjacent or overlapping existing memory block
if (addrStart <= curEnd + 1 && addrEnd + 1 >= curStart)
{
adr_t newStart = (curStart < addrStart) ? curStart : addrStart;
adr_t newEnd = (curEnd < addrEnd) ? addrEnd : curEnd;
adr_t newSize = newEnd - newStart + 1;
i->resize(newSize);
// if resized overlaps the next one, swallow next one
while (i + 1 != vector<TMemory<T, TType>>::end() &&
newEnd + 1 >= (i + 1)->GetStart())
{
adr_t nextStart = (i + 1)->GetStart();
adr_t nextEnd = (i + 1)->GetEnd();
if (nextEnd > newEnd)
{
newEnd = nextEnd;
newSize = newEnd - newStart + 1;
i->resize(newSize);
}
for (adr_t j = nextStart; j <= nextEnd; j++)
i->at(j) = (i + 1)->at(j);
vector<TMemory<T, TType>>::erase(i + 1);
}
// if inserted before current start, some shuffling is needed
if (newStart != curStart)
{
i->SetStart(newStart);
adr_t diff = curStart - newStart;
for (adr_t j = curSize; j > 0; j--)
i->at(newStart + j - 1 + diff) = i->at(newStart + j - 1);
}
if (contents)
{
for (adr_t j = 0; j < memSize; j++)
i->at(addrStart + j) = contents[j];
}
return true;
}
}
}
}
// obviously not adjacent to another area
// do a simple insertion sort - shouldn't be too many areas
for (i = vector<TMemory<T, TType>>::begin(); i != vector<TMemory<T, TType>>::end(); i++)
if (addrStart < i->GetStart())
break;
TMemory<T, TType> &t =
*this->insert(i,
TMemory<T, TType>(addrStart, 0, memType));
if (memSize)
t.resize(memSize);
ResetLast();
// done this way to avoid creating a potentially large temporary object
if (contents && memSize)
{
for (adr_t j = 0; j < memSize; j++)
t.at(addrStart + j) = contents[j];
}
return true;
}
// find memory area index for a given address
adr_t GetMemIndex(adr_t addr)
{
// little speedup for multiple accesses in scattered environments
if (addr >= last.start && addr <= last.end) return last.idx;
for (typename TMemoryArray<T, TType>::size_type i = 0; i < vector<TMemory<T, TType>>::size(); i++)
{
TMemory<T, TType> &mem = this->at(i);
if (mem.GetStart() <= addr && (adr_t)(mem.GetStart() + mem.size()) > addr)
{
last.start = mem.GetStart();
last.end = mem.GetEnd();
last.idx = i;
return i;
}
}
return NO_ADDRESS;
}
TMemory<T, TType> *FindMem(adr_t addr)
{
adr_t idx = GetMemIndex(addr);
if (idx != NO_ADDRESS)
return &vector<TMemory<T, TType>>::at(static_cast<typename TMemory<T, TType>::size_type>(idx));
return NULL;
}
// get item at a given address
T *getat(adr_t addr)
{
TMemory<T, TType> *pmem = FindMem(addr);
return (pmem) ? &pmem->at(addr) : NULL;
}
// get multiple bytes with(out) byte reversal
bool getat(adr_t addr, T *val, adr_t len, bool bReverse = false)
{
adr_t i;
if (bReverse)
for (i = 0; i < len; i++)
{
TMemory<T, TType> *pmem = FindMem(addr + i);
if (!pmem)
return false;
val[len - 1 - i] = pmem->at(addr + i);
}
else
{
for (i = 0; i < len; i++)
{
TMemory<T, TType> *pmem = FindMem(addr + i);
if (!pmem)
return false;
val[i] = pmem->at(addr + i);
}
}
return true;
}
// write item at a given address
bool setat(adr_t addr, T val)
{
TMemory<T, TType> *pmem = FindMem(addr);
if (!pmem) return false;
pmem->at(addr) = val;
return true;
}
// write multiple bytes with(out) byte reversal
bool setat(adr_t addr, T *val, adr_t len, bool bReverse = false)
{
adr_t i;
if (bReverse)
{
for (i = 0; i < len; i++)
if (!setat(addr + i, val[len - 1 - i]))
return false;
}
else
{
for (i = 0; i < len; i++)
if (!setat(addr + i, val[i]))
return false;
}
return true;
}
protected:
struct
{
adr_t start;
adr_t end;
adr_t idx;
} last;
void ResetLast() { last.start = last.end = last.idx = NO_ADDRESS; }
};
/*****************************************************************************/
/* MemAttribute : basic description of a memory cell's attributes */
/*****************************************************************************/
struct MemAttribute
{
unsigned cellSize: 8; /* cell size 1..256 (i.e., +1) */
unsigned memType: 3; /* MemoryType */
unsigned cellType: 3; /* CellType */
unsigned display: 4; /* CellDisplay */
unsigned used: 1; /* used (or not) */
unsigned breakBefore: 1; /* line break in disassembly */
unsigned forcedAddr:1; /* forced addressing */
unsigned relConst:1; /* rel for this is const */
enum Type
{
CellUntyped,
SignedInt,
UnsignedInt,
Float
};
enum Display
{
CellUndisplayable,
DefaultDisplay,
Binary,
Char,
Octal,
Decimal,
Hex,
};
MemAttribute
(
MemoryType memType = Code,
int cellSize = 1,
bool used = true,
Type cellType = UnsignedInt,
Display display = DefaultDisplay,
bool breakBefore = false,
bool forcedAddr = false,
bool relConst = false
)
: cellSize(cellSize - 1), memType(memType), cellType(cellType),
display(display), used(used), breakBefore(breakBefore),
forcedAddr(forcedAddr), relConst(relConst)
{ }
// MemAttribute Getters / Setters
MemoryType GetMemType() { return (MemoryType)memType; }
void SetMemType(MemoryType newType = Code) { memType = (unsigned)newType; }
bool IsUsed() { return !!used; }
void SetUsed(bool bUsed = true) { used = !!bUsed; }
Type GetCellType() { return (Type)cellType; }
void SetCellType(Type newType) { cellType = (unsigned)newType; }
int GetSize() { return cellSize + 1; }
void SetSize(int newSize = 1) { cellSize = (unsigned)(newSize - 1); }
Display GetDisplay() { return (Display)display; }
void SetDisplay(Display newDisp = DefaultDisplay) { display = (unsigned)newDisp; }
bool GetBreakBefore() { return !!breakBefore; }
void SetBreakBefore(bool bOn = true) { breakBefore = !!bOn; }
bool GetForcedAddr() { return !!forcedAddr; }
void SetForcedAddr(bool bOn = true) { forcedAddr = !!bOn; }
bool GetRelConst() { return !!relConst; }
void SetRelConst(bool bOn = true) { relConst = !!bOn; }
};
/*****************************************************************************/
/* MemoryArray : an array of memory areas */
/*****************************************************************************/
class MemoryArray : public TMemoryArray<uint8_t, MemoryType>
{
// currently, no specialization needed
};
#endif // __Memory_h_defined__