-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemorymap.c
More file actions
203 lines (187 loc) · 5.65 KB
/
memorymap.c
File metadata and controls
203 lines (187 loc) · 5.65 KB
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
/*
* memorymap.c
*
* Created on: Nov 22, 2019
* Author: cburke
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "memorymap.h"
void mm_init(MemoryMap* map, int mapSize, char *id) {
// WARNING: id might be an ephemeral string; copy if needed
// Try to allocate memory for map
map->storage = (unsigned char *)malloc(mapSize*sizeof(unsigned char));
if (NULL == map->storage) {
map->maxElements = 0;
fprintf(stderr, "ERROR: mm_init: Insufficient memory to map '%s'.\n", id);
exit(1);
}
memset(map->storage, MM_UNKNOWN, (size_t)(mapSize*sizeof(unsigned char)));
map->maxElements = mapSize;
map->end = map->storage + mapSize - 1;
}
unsigned char mm_type(MemoryMap* map, int offset) {
if (offset < map->maxElements) {
return map->storage[offset] & ~MM_LABEL;
}
return MM_INVALID;
}
int mm_isLabel(MemoryMap* map, int offset) {
if (offset < map->maxElements) {
return ((map->storage[offset] & MM_LABEL) != 0);
}
return 0;
}
void mm_setType(MemoryMap* map, int offset, unsigned char type) {
if (offset < map->maxElements) {
int labelFlag = map->storage[offset] & MM_LABEL;
map->storage[offset] = type | labelFlag;
}
}
void mm_setLabel(MemoryMap* map, int offset, int value) {
if (offset < map->maxElements) {
if (value != 0) {
map->storage[offset] |= MM_LABEL;
}
else {
map->storage[offset] &= ~MM_LABEL;
}
}
}
void _mm_set(MemoryMap* map, int offset, unsigned char type_1, unsigned char type, unsigned char type_n, int count) {
//printf("_mm_set $%04X %c %c %c %d\n", offset, type_1, type, type_n, count);
if (offset+count > map->maxElements) {
fprintf(stderr, "ERROR: _mm_set: Map offset $%05x is beyond the end of the map\n", offset+count);
}
// Error if these bytes aren't all currently "unknown"
unsigned short i;
unsigned char v, t;
if (1 == count) {
// Special case if we have a "first" and a "last" rule for 1 byte
t = type_n;
if (type_1 != type) {
// Assume the 1st byte rule has priority
t = type_1;
}
if (((v = mm_type(map, offset)) != MM_UNKNOWN) && (v != t)) {
fprintf(stderr, "ERROR: _mm_set: Map offset $%04X has two different data types (%c,%c)\n", offset, t, v);
} else {
mm_setType(map, offset, t);
}
} else {
for (i=0; i<count; i++) {
t = (0 == i) ? type_1 : (((count-1) == i) ? type_n : type);
if ((v = mm_type(map, offset+i)) != MM_UNKNOWN) {
fprintf(stderr, "ERROR: _mm_set: Offset $%04X has two different data types (%c,%c)\n", offset+i, t, v);
}
else {
mm_setType(map, offset+i, t);
}
}
}
}
void mm_set(MemoryMap* map, int offset, unsigned char type, int count) {
_mm_set(map, offset, type, type, type, count);
}
void mm_setCode(MemoryMap* map, int offset, int count) {
// For code, first byte is treated differently
_mm_set(map, offset, MM_CODE1, MM_CODE, MM_CODE, count);
}
void mm_setString(MemoryMap* map, int offset, int count) {
// For strings, last byte is treated differently
_mm_set(map, offset, MM_FCS, MM_FCS, MM_FCSN, count);
}
void mm_setFDB(MemoryMap* map, int offset, int count) {
if (count & 1) {
fprintf(stderr, "ERROR: mm_setfdb: Byte count must be even (%d)\n", count);
} else {
// Set in pairs so we alternate FDB and FDB2
int i;
for (i=0; i<count; i+=2) {
_mm_set(map, offset+i, MM_FDB, MM_FDB, MM_FDB2, 2);
}
}
}
int mm_runLength(MemoryMap* map, int offset) {
// Whatever the data type at offset, return the number of bytes
// starting there with the same (or compatible) type (e.g. one instruction)
int count = 0;
int source;
unsigned char type_1, type;
if (offset >= map->maxElements) {
fprintf(stderr, "ERROR: mm_runlength: Map offset $%05X is beyond the end of the map\n", offset);
}
type_1 = mm_type(map, offset);
switch (type_1) {
case MM_FCSN:
// This is a single-byte string -- done
count = 1;
break;
case MM_FCS:
// Multi-byte string -- keep going until MM_FCSN
while ((type=mm_type(map, (source=offset+count))) == MM_FCS) ++count;
if (type != MM_FCSN) {
fprintf(stderr, "ERROR: mm_runlength: String at offset $%04X ended with unexpected type (%c)\n", offset, type);
} else {
++count;
}
break;
case MM_FDB:
// Keep going while FDB or FDB2
while (((type=mm_type(map, (source=offset+count))) == MM_FDB) || (type == MM_FDB2)) ++count;
break;
case MM_CODE1:
case MM_CODEX:
// Start of an instruction; rest of instruction is MM_CODE
++count;
while ((type=mm_type(map, (source=offset+count))) == MM_CODE) ++count;
break;
case MM_CODE:
// Should never happen
fprintf(stderr, "ERROR: mm_runlength: Not on instruction boundary at offset $%04X\n", offset);
count = 1;
break;
case MM_FDB2:
// Should never happen
fprintf(stderr, "ERROR: mm_runlength: Not on FDB boundary at offset $%04X\n", offset);
count = 1;
break;
default:
// Other cases are easy - just look for a continuous run
while ((source=offset+count) < map->maxElements &&
(type=mm_type(map, source)) == type_1) ++count;
break;
}
return count;
}
void mm_dump(MemoryMap* map, int perLine) {
// Note, this dump doesn't show label flags
// One way to do this would be, two characters per byte
// with space for no label, * for label
int i, pos = 0;
if (perLine < 0) perLine = 16;
if (perLine > 64) perLine = 64;
// Generate header
printf(" ");
for (i=0; i<perLine; i++) {
printf("%X",i/16);
}
printf("\n ");
for (i=0; i<perLine; i++) {
printf("%X",i%16);
}
printf("\n ");
for (i=0; i<perLine; i++) {
printf("-");
}
// Generate dump
for (pos = 0; pos < map->maxElements; pos++) {
if (pos%perLine == 0) {
printf("\n%04X: ", pos);
}
printf("%c", map->storage[pos] & ~MM_LABEL);
}
printf("\n");
}