Browse code

Add source code of the assembler compiler

Pawel Jablonski authored on 14/12/2022 19:04:16
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,372 @@
1
+/*
2
+ * Author: Pawel Jablonski
3
+ * E-mail: pj@xirx.net
4
+ * WWW: xirx.net
5
+ * GIT: git.xirx.net
6
+ *
7
+ * License: You can use this code however you like
8
+ * but leave information about the original author.
9
+ * Code is free for non-commercial and commercial use.
10
+ */
11
+
12
+#include "linker.h"
13
+
14
+/**
15
+ * Constructor of the linker
16
+ *
17
+ * @param dataList Data list
18
+ */
19
+Linker::Linker(DataList &dataList) : dataList(dataList)
20
+{
21
+}
22
+
23
+/**
24
+ * Link all parts of the application together and fill addresses
25
+ *
26
+ * @return Status of linking the application
27
+ */
28
+bool Linker::link()
29
+{
30
+	QTextStream out(stdout);
31
+
32
+	unsigned int ramSize = ((this->dataList.getMode() == DataList::Mode::Rom) ? ROM_RAM_SIZE : APP_RAM_SIZE);
33
+	unsigned int flashSize = ((this->dataList.getMode() == DataList::Mode::Rom) ? ROM_FLASH_SIZE : APP_FLASH_SIZE);
34
+
35
+	unsigned int ramOffset = ((this->dataList.getMode() == DataList::Mode::Rom) ? ROM_RAM_OFFSET : APP_RAM_OFFSET);
36
+	unsigned int flashOffset = ((this->dataList.getMode() == DataList::Mode::Rom) ? ROM_FLASH_OFFSET : APP_FLASH_OFFSET);
37
+
38
+	unsigned int ramUsage = 0;
39
+	unsigned int flashUsage = 0;
40
+
41
+	this->flashVector.clear();
42
+
43
+	// Move code to flash
44
+	for(const QSharedPointer<Data> &data : this->dataList)
45
+	{
46
+		// Copy code to flash list
47
+		for(const QSharedPointer<CodeSection> &codeSection : data->getCodeSectionList())
48
+		{
49
+			codeSection->setAddress(flashUsage + flashOffset);
50
+
51
+			for(const QSharedPointer<CodeItem> &codeItem : codeSection->getCodeItemList())
52
+			{
53
+				codeItem->setAddress(flashUsage + flashOffset);
54
+
55
+				flashUsage += static_cast<unsigned int>(codeItem->getDataVector().length());
56
+
57
+				this->flashVector.append(codeItem->getDataVector());
58
+			}
59
+		}
60
+	}
61
+
62
+	// Move data to ram and flash
63
+	for(const QSharedPointer<Data> &data : this->dataList)
64
+	{
65
+		// Count ram
66
+		for(const QSharedPointer<RamItem> &ramItem : data->getRamItemList())
67
+		{
68
+			ramItem->setAddress(ramUsage + ramOffset);
69
+
70
+			ramUsage += ramItem->getDataSize();
71
+		}
72
+
73
+		// Copy flash to flash list
74
+		for(const QSharedPointer<FlashItem> &flashItem : data->getFlashItemList())
75
+		{
76
+			flashItem->setAddress(flashUsage + flashOffset);
77
+
78
+			flashUsage += static_cast<unsigned int>(flashItem->getDataSize());
79
+
80
+			this->flashVector.append(flashItem->getDataVector());
81
+		}
82
+	}
83
+
84
+	if(ramUsage > ramSize)
85
+	{
86
+		out << QString("ERROR: %1 of %2 (%3%) bytes of RAM are used\n").arg(ramUsage).arg(ramSize).arg(QString::asprintf("%.1f", ((static_cast<double>(ramUsage) / static_cast<double>(ramSize)) * 100.0)));
87
+		return(false);
88
+	}
89
+
90
+	if(flashUsage > flashSize)
91
+	{
92
+		out << QString("ERROR: %1 of %2 (%3%) bytes of FLASH are used\n").arg(flashUsage).arg(flashSize).arg(QString::asprintf("%.1f", ((static_cast<double>(flashUsage) / static_cast<double>(flashSize)) * 100.0)));
93
+		return(false);
94
+	}
95
+
96
+	// Update addresses
97
+	for(const QSharedPointer<Data> &data : this->dataList)
98
+	{
99
+		for(const QSharedPointer<CodeSection> &codeSection : data->getCodeSectionList())
100
+		{
101
+			for(const QSharedPointer<CodeItem> &codeItem : codeSection->getCodeItemList())
102
+			{
103
+				QHashIterator<QString, unsigned int> it(codeItem->getToFillUpHash());
104
+
105
+				while(it.hasNext())
106
+				{
107
+					it.next();
108
+
109
+					const QString &label = it.key();
110
+					unsigned int offset = it.value();
111
+
112
+					unsigned int address;
113
+
114
+					offset += (codeItem->getAddress() - flashOffset);
115
+
116
+					bool isOk = false;
117
+
118
+					if((label.left(1) == ".") || (label.left(1) == "*"))
119
+					{
120
+						if(this->findAddress(*data, label, address))
121
+						{
122
+							this->flashVector.replace(static_cast<int>(offset), static_cast<unsigned char>(address % 256));
123
+							this->flashVector.replace(static_cast<int>(offset + 1), static_cast<unsigned char>(address / 256));
124
+
125
+							isOk = true;
126
+						}
127
+					}
128
+					else if(!label.leftRef(3).compare(QString("low"), Qt::CaseInsensitive))
129
+					{
130
+						QString tLabel = label.mid(4, (label.length() - 5));
131
+
132
+						if(this->findAddress(*data, tLabel, address))
133
+						{
134
+							this->flashVector.replace(static_cast<int>(offset), static_cast<unsigned char>(address % 256));
135
+
136
+							isOk = true;
137
+						}
138
+					}
139
+					else if(!label.leftRef(4).compare(QString("high"), Qt::CaseInsensitive))
140
+					{
141
+						QString tLabel = label.mid(5, (label.length() - 6));
142
+
143
+						if(this->findAddress(*data, tLabel, address))
144
+						{
145
+							this->flashVector.replace(static_cast<int>(offset), static_cast<unsigned char>(address / 256));
146
+
147
+							isOk = true;
148
+						}
149
+					}
150
+
151
+					if(!isOk)
152
+					{
153
+						out << QString("ERROR: Unknown label name \"%1\" at line %2 in file: \"%3\"\n").arg(label).arg(codeItem->getLine()).arg(data->getFileName());
154
+						return(false);
155
+					}
156
+				}
157
+			}
158
+		}
159
+	}
160
+
161
+	out << QString("INFO: %1 of %2 (%3%) bytes of RAM are used\n").arg(ramUsage).arg(ramSize).arg(QString::asprintf("%.1f", ((static_cast<double>(ramUsage) / static_cast<double>(ramSize)) * 100.0)));
162
+	out << QString("INFO: %1 of %2 (%3%) bytes of FLASH are used\n").arg(flashUsage).arg(flashSize).arg(QString::asprintf("%.1f", ((static_cast<double>(flashUsage) / static_cast<double>(flashSize)) * 100.0)));
163
+
164
+	return(true);
165
+}
166
+
167
+/**
168
+ * Save the binary to the file
169
+ *
170
+ * @param path Path to the binary file
171
+ * @param pathMap Path to the map file
172
+ *
173
+ * @return Status of saving data to the file
174
+ */
175
+bool Linker::saveFile(const QString &path, const QString &pathMap)
176
+{
177
+	if(!this->flashVector.empty())
178
+	{
179
+		if(this->flashVector.size() > ROM_FLASH_SIZE)
180
+		{
181
+			return(false);
182
+		}
183
+
184
+		if(this->dataList.getMode() == DataList::Mode::Rom)
185
+		{
186
+			this->flashVector.append(QVector<unsigned char>((ROM_FLASH_SIZE - this->flashVector.size()), 0));
187
+		}
188
+
189
+		QFile file(path);
190
+
191
+		if(file.open(QIODevice::WriteOnly))
192
+		{
193
+			file.write(reinterpret_cast<const char *>(this->flashVector.constData()), this->flashVector.size());
194
+			file.close();
195
+		}
196
+		else
197
+		{
198
+			return(false);
199
+		}
200
+	}
201
+	else
202
+	{
203
+		return(false);
204
+	}
205
+
206
+	if(this->dataList.getMode() == DataList::Mode::Rom)
207
+	{
208
+		QFile file(pathMap);
209
+
210
+		if(file.open(QIODevice::WriteOnly))
211
+		{
212
+			for(const QSharedPointer<RamItem> &ramItem : this->dataList.getExternalRamItemList())
213
+			{
214
+				QString line = QString("external var %1 = 0x%2\n").arg(ramItem->getName()).arg(ramItem->getAddress(), 4, 16, QChar('0'));
215
+
216
+				file.write(line.toUtf8());
217
+			}
218
+
219
+			for(const QSharedPointer<FlashItem> &flashItem : this->dataList.getExternalFlashItemList())
220
+			{
221
+				QString line = QString("external const %1 = 0x%2\n").arg(flashItem->getName()).arg(flashItem->getAddress(), 4, 16, QChar('0'));
222
+
223
+				file.write(line.toUtf8());
224
+			}
225
+
226
+			for(const QSharedPointer<CodeSection> &codeSection : this->dataList.getExternalCodeSectionList())
227
+			{
228
+				QString line = QString("%1 = 0x%2\n").arg(codeSection->getName()).arg(codeSection->getAddress(), 4, 16, QChar('0'));
229
+
230
+				file.write(line.toUtf8());
231
+			}
232
+
233
+			file.close();
234
+		}
235
+		else
236
+		{
237
+			return(false);
238
+		}
239
+	}
240
+
241
+	return(true);
242
+}
243
+
244
+/**
245
+ * Find the correct address in memory
246
+ *
247
+ * @param data Data of the compiled application
248
+ * @param label Label name to find
249
+ * @param address Found address
250
+ *
251
+ * @return Status of searching the address
252
+ */
253
+bool Linker::findAddress(Data &data, const QString &label, unsigned int &address)
254
+{
255
+	QString name;
256
+
257
+	if(label.contains(QRegularExpression(R"(^(\.[0-9a-zA-Z_-]+)$)")))
258
+	{
259
+		name = label;
260
+
261
+		return(this->findCodeAddress(data, name, address));
262
+	}
263
+	else if(label.contains(QRegularExpression(R"(^(\*[0-9a-zA-Z_-]+)$)")))
264
+	{
265
+		name = label.mid(1);
266
+
267
+		return(this->findMemoryAddress(data, name, address));
268
+	}
269
+	else if(label.contains(QRegularExpression(R"(^(\*[0-9a-zA-Z_-]+\[[0-9]+\])$)")))
270
+	{
271
+		int cOffset = label.indexOf("[");
272
+		name = label.mid(1, (cOffset - 1));
273
+		unsigned int offset = label.midRef((cOffset + 1), (label.length() - cOffset - 2)).toUInt();
274
+
275
+		if(this->findMemoryAddress(data, name, address))
276
+		{
277
+			address += offset;
278
+
279
+			return(true);
280
+		}
281
+	}
282
+
283
+	return(false);
284
+}
285
+
286
+/**
287
+ * Find the correct address of code in memory
288
+ *
289
+ * @param data Data of the compiled application
290
+ * @param name Name to find
291
+ * @param address Found address
292
+ *
293
+ * @return Status of searching the address
294
+ */
295
+bool Linker::findCodeAddress(Data &data, const QString &name, unsigned int &address)
296
+{
297
+	for(const QSharedPointer<CodeSection> &codeSection : data.getCodeSectionList())
298
+	{
299
+		if(!codeSection->getName().compare(name, Qt::CaseInsensitive))
300
+		{
301
+			address = codeSection->getAddress();
302
+
303
+			return(true);
304
+		}
305
+	}
306
+
307
+	for(const QSharedPointer<CodeSection> &codeSection : this->dataList.getGlobalCodeSectionList())
308
+	{
309
+		if(!codeSection->getName().compare(name, Qt::CaseInsensitive))
310
+		{
311
+			address = codeSection->getAddress();
312
+
313
+			return(true);
314
+		}
315
+	}
316
+
317
+	return(false);
318
+}
319
+
320
+/**
321
+ * Find the correct address of variable or const in memory
322
+ *
323
+ * @param data Data of the compiled application
324
+ * @param name Name to find
325
+ * @param address Found address
326
+ *
327
+ * @return Status of searching the address
328
+ */
329
+bool Linker::findMemoryAddress(Data &data, const QString &name, unsigned int &address)
330
+{
331
+	for(const QSharedPointer<RamItem> &ramItem : data.getRamItemList())
332
+	{
333
+		if(!ramItem->getName().compare(name, Qt::CaseInsensitive))
334
+		{
335
+			address = ramItem->getAddress();
336
+
337
+			return(true);
338
+		}
339
+	}
340
+
341
+	for(const QSharedPointer<FlashItem> &flashItem : data.getFlashItemList())
342
+	{
343
+		if(!flashItem->getName().compare(name, Qt::CaseInsensitive))
344
+		{
345
+			address = flashItem->getAddress();
346
+
347
+			return(true);
348
+		}
349
+	}
350
+
351
+	for(const QSharedPointer<RamItem> &ramItem : this->dataList.getGlobalRamItemList())
352
+	{
353
+		if(!ramItem->getName().compare(name, Qt::CaseInsensitive))
354
+		{
355
+			address = ramItem->getAddress();
356
+
357
+			return(true);
358
+		}
359
+	}
360
+
361
+	for(const QSharedPointer<FlashItem> &flashItem : this->dataList.getGlobalFlashItemList())
362
+	{
363
+		if(!flashItem->getName().compare(name, Qt::CaseInsensitive))
364
+		{
365
+			address = flashItem->getAddress();
366
+
367
+			return(true);
368
+		}
369
+	}
370
+
371
+	return(false);
372
+}