4a7fe1b7680e4226f1d9b8b4a164fdac6e6bad74
[rmac] / mark.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // MARK.C - A record of things that are defined relative to any of the sections
4 // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
7 //
8
9 #include "mark.h"
10 #include "error.h"
11 #include "object.h"
12 #include "riscasm.h"
13
14
15 MCHUNK * firstmch;              // First mark chunk
16 MCHUNK * curmch;                // Current mark chunk
17 PTR markptr;                    // Deposit point in current mark chunk
18 LONG mcalloc;                   // #bytes alloc'd to current mark chunk
19 LONG mcused;                    // #bytes used in current mark chunk
20 uint16_t curfrom;               // Current "from" section
21
22
23 //#define DEBUG_IMAGE_MARKING
24
25
26 //
27 // Initialize marker
28 //
29 void InitMark(void)
30 {
31         firstmch = curmch = NULL;
32         mcalloc = mcused = 0;
33         curfrom = 0;
34 }
35
36
37 //
38 // Wrap up marker (called after final mark is made)
39 //
40 void StopMark(void)
41 {
42         if (curmch)
43         {
44                 *markptr.wp = MCHEND;           // Mark end of block
45                 curmch->mcused = mcused;        // Update #used in mark block
46         }
47 }
48
49
50 //
51 // Mark a word or longword relocatable
52 //
53 int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol)
54 {
55 #ifdef DEBUG_IMAGE_MARKING
56 printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to, size, symbol);
57 if (symbol)
58         printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
59 #endif
60
61         if ((mcalloc - mcused) < MIN_MARK_MEM)
62                 amark();
63
64         uint16_t flags = (size | to);
65
66         if (from != curfrom)
67                 flags |= MCHFROM;
68
69         if (symbol != NULL)
70                 flags |= MSYMBOL;
71
72         mcused += sizeof(WORD) + sizeof(LONG);
73         *markptr.wp++ = flags;
74         *markptr.lp++ = loc;
75
76         if (flags & MCHFROM)
77         {
78                 curfrom = from;
79                 *markptr.wp++ = from;
80                 mcused += sizeof(WORD);
81         }
82
83         if (flags & MSYMBOL)
84         {
85                 *markptr.sy++ = symbol;
86                 mcused += sizeof(SYM *);
87         }
88
89         *markptr.wp = 0x0000;
90
91         return 0;
92 }
93
94
95 //
96 // Allocate another chunk of mark space
97 //
98 int amark(void)
99 {
100 //      MCHUNK * p;
101
102         // Alloc mark block header (and data) and set it up.
103 //      p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
104         MCHUNK * p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
105         p->mcnext = NULL;
106         p->mcalloc = MARK_ALLOC_INCR;
107         p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
108
109         if (curmch)
110         {
111                 // Link onto previous chunk 
112                 *markptr.wp++ = MCHEND;         // Mark end of block 
113                 curmch->mcused = mcused;
114                 curmch->mcnext = p;
115         }
116
117         if (!firstmch)
118                 firstmch = p;
119
120         curmch = p;                                             // Setup global vars 
121         markptr = p->mcptr;
122         mcalloc = MARK_ALLOC_INCR;
123         mcused = 0;
124
125         return 0;
126 }
127
128
129 //
130 // Make mark image for BSD .o file
131 //
132 uint32_t bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg)
133 {
134         MCHUNK * mch;                           // Mark chunk
135         PTR p;                                          // Source point from within mark chunk
136         uint16_t from;                          // Section fixups are currently FROM
137         uint16_t w;                                     // A word (temp)
138         uint32_t loc;                           // Location (temp) 
139         SYM * symbol;                           // Symbols (temp)
140         uint8_t * wp;                           // Pointer into raw relocation info
141         uint8_t * dp;                           // Deposit point for RELMOD info
142         uint32_t diff;                          // Difference to relocate (RELMOD)
143         uint32_t raddr, rflag = 0;      // BSD relocation address and flags
144         uint32_t rsize;                         // Relocation size
145         int validsegment = 0;           // Valid segment being processed
146
147 #ifdef DEBUG_IMAGE_MARKING
148 printf("bsdmarkimg():\n");
149 #endif
150         // Initialise relocation size
151         rsize = 0;
152         chptr = mp;
153         from = 0;
154
155         for(mch=firstmch; mch!=NULL; mch=mch->mcnext)
156         {
157                 for(p=mch->mcptr;;)
158                 {
159                         w = *p.wp++;                    // Next mark entry
160
161                         if (w & MCHEND)
162                                 break;                          // End of mark chunk
163
164                         // Get mark record
165                         symbol = NULL;
166                         loc = *p.lp++;                  // Mark location
167
168                         if (w & MCHFROM)
169                         {
170                                 // Maybe change "from" section
171                                 from = *p.wp++;
172
173                                 if (obj_format == BSD)
174                                 {
175                                         if (reqseg == TEXT)
176                                         {
177                                                 // Requested segment is TEXT
178                                                 if (from == TEXT)
179                                                         validsegment = 1; 
180                                                 else
181                                                         validsegment = 0;
182                                         }
183                                         else
184                                         {
185                                                 // Requested segment is DATA
186                                                 if (from == DATA)
187                                                         validsegment = 1; 
188                                                 else
189                                                         validsegment = 0;
190                                         }
191                                 }
192                         }
193
194                         if (w & MSYMBOL)                        // Maybe includes a symbol
195                                 symbol = *p.sy++;
196
197                         if (obj_format == BSD)
198                         {
199                                 raddr = loc;                    // Set relocation address
200
201                                 if (validsegment)
202 #ifdef DEBUG_IMAGE_MARKING
203 {
204 printf(" validsegment: raddr = $%08X\n", raddr);
205 #endif
206                                         D_long(raddr);          // Write relocation address
207 #ifdef DEBUG_IMAGE_MARKING
208 }
209 #endif
210
211                                 if (w & MPCREL)
212                                         rflag = 0x000000A0;     // PC-relative fixup
213                                 else
214                                         rflag = 0x00000040;     // Absolute fixup
215
216 // This flag tells the linker to WORD swap the LONG when doing the fixup.
217                                 if (w & MMOVEI)
218 //{
219 //printf("bsdmarkimg: ORing $01 to rflag (MMOVEI) [symbol=%s]...\n", symbol->sname);
220                                         rflag |= 0x00000001;
221 //}
222                         }
223
224                         // Compute mark position in relocation information;
225                         // in RELMOD mode, get address of data to fix up.
226                         if (from == DATA)
227                                 loc += tsize;
228
229                         wp = (uint8_t *)(mp + loc);
230
231                         if (symbol)
232                         {
233                                 // Deposit external reference
234                                 if (obj_format == BSD)
235                                 {
236                                         rflag |= 0x00000010;                    // Set external reloc flag bit
237                                         rflag |= (symbol->senv << 8);   // Put symbol index in flags
238
239 // Looks like this is completely unnecessary (considering it does the wrong thing!)
240 #if 0
241                                         if (symbol->sattre & RISCSYM)
242 {
243 printf("bsdmarkimg: ORing $01 to rflag (RISCSYM) [symbol=%s]...\n", symbol->sname);
244                                                 rflag |= 0x00000001;
245 }
246 #endif
247
248                                         if (validsegment)
249                                         {
250 #ifdef DEBUG_IMAGE_MARKING
251 printf("  validsegment(2): rflag = $%08X\n", rflag);
252 #endif
253                                                 D_long(rflag);                          // Write relocation flags
254                                                 rsize += 8;                                     // Increment relocation size
255                                         }
256                                 }
257                         }
258                         else
259                         {
260                                 if (obj_format == BSD)
261                                 {
262 #ifdef DEBUG_IMAGE_MARKING
263 printf("  w = $%04X\n", w);
264 #endif
265                                         w &= TDB;                                               // Set reloc flags to segment
266
267                                         switch (w)
268                                         {
269                                         case TEXT: rflag |= 0x00000400; break;
270                                         case DATA: rflag |= 0x00000600; break;
271                                         case BSS:  rflag |= 0x00000800; break;
272                                         }
273
274                                         if (validsegment)
275                                         {
276 #ifdef DEBUG_IMAGE_MARKING
277 printf("  validsegment(3): rflag = $%08X\n", rflag);
278 #endif
279                                                 D_long(rflag);                          // Write relocation flags
280                                                 rsize += 8;                                     // Increment relocation size
281                                         }
282
283                                         w &= TDB;
284
285                                         if (validsegment)
286                                         {
287                                                 if (w & (DATA|BSS))
288                                                 {
289                                                         dp = objImage + BSDHDRSIZE + loc;
290                                                         diff = ((LONG)(*dp++ & 0xFF)) << 24;
291                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 16;
292                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 8;
293                                                         diff |= (LONG)(*dp & 0xFF);
294                                                         DEBUG printf("diff=%ux ==> ", diff);
295 #ifdef DEBUG_IMAGE_MARKING
296 printf("  validsegment(4): diff = $%08X --> ", diff);
297 #endif
298         
299                                                         if (rflag & 0x01)
300                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
301
302                                                         diff += sect[TEXT].sloc;
303
304                                                         if (w == BSS)
305                                                                 diff += sect[DATA].sloc;
306
307                                                         if (rflag & 0x01)
308                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
309
310                                                         dp = objImage + BSDHDRSIZE + loc;
311                                                         *dp++ = (char)(diff >> 24);
312                                                         *dp++ = (char)(diff >> 16);
313                                                         *dp++ = (char)(diff >> 8);
314                                                         *dp = (char)diff;
315                                                         DEBUG printf("%ux\n", diff);
316 #ifdef DEBUG_IMAGE_MARKING
317 printf("$%08X\n", diff);
318 #endif
319                                                 }
320                                         }
321                                 }
322                         }
323                 }
324         }
325
326         // Return relocation size
327         if (obj_format == BSD)
328 #ifdef DEBUG_IMAGE_MARKING
329 {
330 printf("  rsize = $%X\n", rsize);
331 #endif
332                 return rsize;                                        
333 #ifdef DEBUG_IMAGE_MARKING
334 }
335 #endif
336
337         return siz;
338 }