1 /* asmcode.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Verwaltung der Code-Datei */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12 #include <string.h>
13
14 #include "version.h"
15 #include "endian.h"
16 #include "chunks.h"
17 #include "as.h"
18 #include "asmdef.h"
19 #include "errmsg.h"
20 #include "strutil.h"
21 #include "asmsub.h"
22 #include "asmpars.h"
23 #include "asmrelocs.h"
24 #include "asmlist.h"
25 #include "asmlabel.h"
26
27 #include "asmcode.h"
28
29 #define CodeBufferSize 512
30
31 static Word LenSoFar;
32 static LongInt RecPos, LenPos;
33 static Boolean ThisRel;
34
35 static Word CodeBufferFill;
36 static Byte *CodeBuffer;
37
38 PPatchEntry PatchList, PatchLast;
39 PExportEntry ExportList, ExportLast;
40 LongInt SectSymbolCounter;
41 String SectSymbolName;
42
FlushBuffer(void)43 static void FlushBuffer(void)
44 {
45 if (CodeBufferFill > 0)
46 {
47 if (fwrite(CodeBuffer, 1, CodeBufferFill, PrgFile) != CodeBufferFill)
48 ChkIO(ErrNum_FileWriteError);
49 CodeBufferFill = 0;
50 }
51 }
52
DreheCodes(void)53 void DreheCodes(void)
54 {
55 int z;
56 LongInt l = CodeLen * Granularity();
57
58 switch (ActListGran)
59 {
60 case 2:
61 for (z = 0; z < l >> 1; z++)
62 WAsmCode[z] = ((WAsmCode[z] & 0xff) << 8) + ((WAsmCode[z] & 0xff00) >> 8);
63 break;
64 case 4:
65 for (z = 0; z < l >> 2; z++)
66 {
67 LongWord Dest;
68 int z2;
69
70 for (z2 = 0, Dest = 0; z2 < 4; z2++)
71 {
72 Dest = (Dest << 8) | (DAsmCode[z] & 0xff);
73 DAsmCode[z] >>= 8;
74 }
75 DAsmCode[z] = Dest;
76 }
77 break;
78 }
79 }
80
WrPatches(void)81 static void WrPatches(void)
82 {
83 LongWord Cnt, ExportCnt, StrLen;
84 Byte T8;
85
86 if (PatchList || ExportList)
87 {
88 /* find out length of string field */
89
90 Cnt = StrLen = 0;
91 for (PatchLast = PatchList; PatchLast; PatchLast = PatchLast->Next)
92 {
93 Cnt++;
94 StrLen += (PatchLast->len = strlen(PatchLast->Ref) + 1);
95 }
96 ExportCnt = 0;
97 for (ExportLast = ExportList; ExportLast; ExportLast = ExportLast->Next)
98 {
99 ExportCnt++;
100 StrLen += (ExportLast->len = strlen(ExportLast->Name) + 1);
101 }
102
103 /* write header */
104
105 T8 = FileHeaderRelocInfo;
106 if (fwrite(&T8, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
107 if (!Write4(PrgFile, &Cnt)) ChkIO(ErrNum_FileWriteError);
108 if (!Write4(PrgFile, &ExportCnt)) ChkIO(ErrNum_FileWriteError);
109 if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
110
111 /* write patch entries */
112
113 StrLen = 0;
114 for (PatchLast = PatchList; PatchLast; PatchLast = PatchLast->Next)
115 {
116 if (!Write8(PrgFile, &(PatchLast->Address))) ChkIO(ErrNum_FileWriteError);
117 if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
118 if (!Write4(PrgFile, &(PatchLast->RelocType))) ChkIO(ErrNum_FileWriteError);
119 StrLen += PatchLast->len;
120 }
121
122 /* write export entries */
123
124 for (ExportLast = ExportList; ExportLast; ExportLast = ExportLast->Next)
125 {
126 if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
127 if (!Write4(PrgFile, &(ExportLast->Flags))) ChkIO(ErrNum_FileWriteError);
128 if (!Write8(PrgFile, &(ExportLast->Value))) ChkIO(ErrNum_FileWriteError);
129 StrLen += ExportLast->len;
130 }
131
132 /* write string table, free structures */
133
134 while (PatchList)
135 {
136 PatchLast = PatchList;
137 if (fwrite(PatchLast->Ref, 1, PatchLast->len, PrgFile) != PatchLast->len) ChkIO(ErrNum_FileWriteError);
138 free(PatchLast->Ref);
139 PatchList = PatchLast->Next;
140 free(PatchLast);
141 }
142 PatchLast = NULL;
143
144 while (ExportList)
145 {
146 ExportLast = ExportList;
147 if (fwrite(ExportLast->Name, 1, ExportLast->len, PrgFile) != ExportLast->len) ChkIO(ErrNum_FileWriteError);
148 free(ExportLast->Name);
149 ExportList = ExportLast->Next;
150 free(ExportLast);
151 }
152 ExportLast = NULL;
153 }
154 }
155
156 /*--- neuen Record in Codedatei anlegen. War der bisherige leer, so wird ---
157 ---- dieser ueberschrieben. ------------------------------------------------*/
158
WrRecHeader(void)159 static void WrRecHeader(void)
160 {
161 Byte b;
162
163 /* assume simple record without relocation info */
164
165 ThisRel = RelSegs;
166 b = ThisRel ? FileHeaderRelocRec : FileHeaderDataRec;
167 if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
168 if (fwrite(&HeaderID, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
169 b = ActPC; if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
170 b = Grans[ActPC]; if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
171 fflush(PrgFile);
172 }
173
NewRecord(LargeWord NStart)174 void NewRecord(LargeWord NStart)
175 {
176 LongInt h;
177 LongWord PC;
178 Byte Header;
179
180 /* flush remaining code in buffer */
181
182 FlushBuffer();
183
184 /* zero length record which may be deleted ? */
185 /* do not write out patches at this place - they
186 will be merged with the next record. */
187
188 if (LenSoFar == 0)
189 {
190 if (fseek(PrgFile, RecPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
191 WrRecHeader();
192 h = NStart;
193 if (!Write4(PrgFile, &h)) ChkIO(ErrNum_FileWriteError);
194 LenPos = ftell(PrgFile);
195 if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
196 }
197
198 /* otherwise full record */
199
200 else
201 {
202 /* store current position (=end of file) */
203
204 h = ftell(PrgFile);
205
206 /* do we have reloc. info? - then change record type */
207
208 if (PatchList || ExportList)
209 {
210 fflush(PrgFile);
211 if (fseek(PrgFile, RecPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
212 Header = ThisRel ? FileHeaderRRelocRec : FileHeaderRDataRec;
213 if (fwrite(&Header, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
214 }
215
216 /* fill in length of record */
217
218 fflush(PrgFile);
219 if (fseek(PrgFile, LenPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
220 if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
221
222 /* go back to end of file */
223
224 if (fseek(PrgFile, h, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
225
226 /* write out reloc info */
227
228 WrPatches();
229
230 /* store begin of new code record */
231
232 RecPos = ftell(PrgFile);
233
234 LenSoFar = 0;
235 WrRecHeader();
236 ThisRel = RelSegs;
237 PC = NStart;
238 if (!Write4(PrgFile, &PC)) ChkIO(ErrNum_FileWriteError);
239 LenPos = ftell(PrgFile);
240 if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
241 }
242 #if 0
243 /* put in the hidden symbol for the relocatable segment ? */
244
245 if ((RelSegs) && (strcmp(CurrFileName, "INTERNAL")))
246 {
247 as_snprintf(SectSymbolName, sizeof(SectSymbolName), "__%s_%d",
248 NamePart(CurrFileName), (int)(SectSymbolCounter++));
249 AddExport(SectSymbolName, ProgCounter());
250 }
251 #endif
252 }
253
254 /*--- Codedatei eroeffnen --------------------------------------------------*/
255
OpenFile(void)256 void OpenFile(void)
257 {
258 Word h;
259
260 errno = 0;
261 PrgFile = fopen(OutName, OPENWRMODE);
262 if (!PrgFile) ChkIO(ErrNum_OpeningFile);
263
264 errno = 0;
265 h = FileMagic;
266 if (!Write2(PrgFile,&h)) ChkIO(ErrNum_FileWriteError);
267
268 CodeBufferFill = 0;
269 RecPos = ftell(PrgFile);
270 LenSoFar = 0;
271 NewRecord(PCs[ActPC]);
272 }
273
274 /*---- Codedatei schliessen -------------------------------------------------*/
275
CloseFile(void)276 void CloseFile(void)
277 {
278 Byte Head;
279 String h;
280 LongWord Adr;
281
282 as_snprintf(h, sizeof(h), "AS %s/%s-%s", Version, ARCHPRNAME, ARCHSYSNAME);
283
284 NewRecord(PCs[ActPC]);
285 fseek(PrgFile, RecPos, SEEK_SET);
286
287 if (StartAdrPresent)
288 {
289 Head = FileHeaderStartAdr;
290 if (fwrite(&Head,sizeof(Head), 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
291 Adr = StartAdr;
292 if (!Write4(PrgFile,&Adr)) ChkIO(ErrNum_FileWriteError);
293 }
294
295 Head = FileHeaderEnd;
296 if (fwrite(&Head,sizeof(Head), 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
297 if (fwrite(h, 1, strlen(h), PrgFile) != strlen(h)) ChkIO(ErrNum_FileWriteError);
298 fclose(PrgFile);
299 if (Magic)
300 unlink(OutName);
301 }
302
303 /*--- erzeugten Code einer Zeile in Datei ablegen ---------------------------*/
304
WriteBytes(void)305 void WriteBytes(void)
306 {
307 Word ErgLen;
308
309 if (CodeLen == 0)
310 return;
311 ErgLen = CodeLen * Granularity();
312 if ((TurnWords != 0) != (BigEndian != 0))
313 DreheCodes();
314 if (((LongInt)LenSoFar) + ((LongInt)ErgLen) > 0xffff)
315 NewRecord(PCs[ActPC]);
316 if (CodeBufferFill + ErgLen < CodeBufferSize)
317 {
318 memcpy(CodeBuffer + CodeBufferFill, BAsmCode, ErgLen);
319 CodeBufferFill += ErgLen;
320 }
321 else
322 {
323 FlushBuffer();
324 if (ErgLen < CodeBufferSize)
325 {
326 memcpy(CodeBuffer, BAsmCode, ErgLen);
327 CodeBufferFill = ErgLen;
328 }
329 else if (fwrite(BAsmCode, 1, ErgLen, PrgFile) != ErgLen)
330 ChkIO(ErrNum_FileWriteError);
331 }
332 LenSoFar += ErgLen;
333 if ((TurnWords != 0) != (BigEndian != 0))
334 DreheCodes();
335 }
336
RetractWords(Word Cnt)337 void RetractWords(Word Cnt)
338 {
339 Word ErgLen;
340
341 ErgLen = Cnt * Granularity();
342 if (LenSoFar < ErgLen)
343 {
344 WrError(ErrNum_ParNotPossible);
345 return;
346 }
347
348 if (MakeUseList)
349 DeleteChunk(SegChunks + ActPC, ProgCounter() - Cnt, Cnt);
350
351 PCs[ActPC] -= Cnt;
352
353 if (CodeBufferFill >= ErgLen)
354 CodeBufferFill -= ErgLen;
355 else
356 {
357 if (fseek(PrgFile, -(ErgLen - CodeBufferFill), SEEK_CUR) == -1)
358 ChkIO(ErrNum_FileWriteError);
359 CodeBufferFill = 0;
360 }
361
362 LenSoFar -= ErgLen;
363
364 Retracted = True;
365 }
366
367 /*!------------------------------------------------------------------------
368 * \fn InsertPadding(unsigned NumBytes, Boolean OnlyReserve)
369 * \brief insert padding bytes into code
370 * \param NumBytes # of bytes to add
371 * \param OnlyReserve write code or only reserve?
372 * ------------------------------------------------------------------------ */
373
InsertPadding(unsigned NumBytes,Boolean OnlyReserve)374 void InsertPadding(unsigned NumBytes, Boolean OnlyReserve)
375 {
376 Boolean SaveDontPrint = DontPrint;
377 LargeWord OldValue = EProgCounter();
378
379 /* write/reserve code */
380
381 SetMaxCodeLen(NumBytes);
382 DontPrint = OnlyReserve;
383 memset(BAsmCode, 0, CodeLen = NumBytes);
384 WriteCode();
385 MakeList("<padding>");
386
387 /* fix up possible label value so it points to the actual code */
388
389 LabelModify(OldValue, EProgCounter());
390
391 CodeLen = 0;
392 DontPrint = SaveDontPrint;
393 }
394
asmcode_init(void)395 void asmcode_init(void)
396 {
397 PatchList = PatchLast = NULL;
398 ExportList = ExportLast = NULL;
399 CodeBuffer = (Byte*) malloc(sizeof(Byte) * (CodeBufferSize + 1));
400 }
401