Fixed .cargs problem, more code cleanup/fixup
[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 "risca.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 WORD curfrom;                   // Current "from" section
21
22
23 //
24 // Initialize Marker
25 //
26 void init_mark(void)
27 {
28         firstmch = curmch = NULL;
29         mcalloc = mcused = 0;
30         curfrom = 0;
31 }
32
33
34 //
35 // Wrap up marker (called after final mark is made)
36 //
37 void stopmark(void)
38 {
39         if (curmch)
40         {
41                 *markptr.wp = MCHEND;                                 // Mark end of block
42                 curmch->mcused = mcused;                              // Update #used in mark block
43         }
44 }
45
46
47 //
48 // Mark a word or longword relocatable
49 //
50 int rmark(int from, LONG loc, int to, int size, SYM * symbol)
51 {
52         WORD w;
53
54         if ((mcalloc - mcused) < MIN_MARK_MEM)
55                 amark();
56
57         w = (WORD)(size | to);
58
59         if (from != curfrom)
60                 w |= MCHFROM;
61
62         if (symbol != NULL)
63                 w |= MSYMBOL;
64
65         mcused += sizeof(WORD) + sizeof(LONG);
66         *markptr.wp++ = w;
67         *markptr.lp++ = loc;
68
69         if (w & MCHFROM)
70         {
71                 *markptr.wp++ = (WORD)from;
72                 curfrom = (WORD)from;
73                 mcused += sizeof(WORD);
74         }
75
76         if (w & MSYMBOL)
77         {
78                 *markptr.sy++ = symbol;
79                 mcused += sizeof(LONG);
80         }
81
82         *markptr.wp = 0x0000;
83
84         return 0;
85 }
86
87
88 //
89 // Allocate another chunk of mark space
90 //
91 int amark(void)
92 {
93         MCHUNK * p;
94
95         // Alloc mark block header (and data) and set it up.
96 //      p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
97         p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
98         p->mcnext = NULL;
99         p->mcalloc = MARK_ALLOC_INCR;
100         p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
101
102         if (curmch)
103         {                                             // Link onto previous chunk 
104                 *markptr.wp++ = MCHEND;                               // Mark end of block 
105                 curmch->mcused = mcused;
106                 curmch->mcnext = p;
107         }
108
109         if (!firstmch)
110                 firstmch = p;
111
112         curmch = p;                                              // Setup global vars 
113         markptr = p->mcptr;
114         mcalloc = MARK_ALLOC_INCR;
115         mcused = 0;
116
117         return 0;
118 }
119
120
121 //
122 // Make mark image for BSD .o file
123 //
124 LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg)
125 {
126         MCHUNK * mch;                                             // Mark chunk
127         PTR p;                                                   // Source point from within mark chunk
128         WORD from;                                               // Section fixups are currently FROM
129         WORD w;                                                  // A word (temp)
130         LONG loc;                                                // Location (temp) 
131         SYM * symbol;                                             // Symbols (temp)
132         char * wp;                                                // Pointer into raw relocation info
133         char * dp;                                                // Deposit point for RELMOD info
134         LONG diff;                                               // Difference to relocate (RELMOD)
135         LONG raddr, rflag = 0;                                   // BSD relocation address and flags
136         LONG rsize;                                              // Relocation size
137         int validsegment = 0;                                    // Valid segment being processed
138
139         rsize = 0;                                               // Initialise relocation size
140         chptr = mp;
141
142         from = 0;
143         for(mch = firstmch; mch != NULL; mch = mch->mcnext)
144         {
145                 for(p=mch->mcptr;;)
146                 {
147                         w = *p.wp++;                                       // Next mark entry
148
149                         if (w & MCHEND)
150                                 break;                              // End of mark chunk
151
152                         // Get mark record
153                         symbol = NULL;
154                         loc = *p.lp++;                                     // Mark location
155
156                         if (w & MCHFROM)
157                         {                                  // Maybe change "from" section
158                                 from = *p.wp++;
159
160                                 if (obj_format == BSD)
161                                 {
162                                         if (reqseg == TEXT)
163                                         {                         // Requested segment is TEXT
164                                                 if (from == TEXT)
165                                                         validsegment = 1; 
166                                                 else
167                                                         validsegment = 0;
168                                         }
169                                         else
170                                         {                                     // Requested segment is DATA
171                                                 if (from == DATA)
172                                                         validsegment = 1; 
173                                                 else
174                                                         validsegment = 0;
175                                         }
176                                 }
177                         }
178
179                         if (w & MSYMBOL)                                    // Maybe includes a symbol
180                                 symbol = *p.sy++;
181
182                         if (obj_format == BSD)
183                         {
184                                 raddr = loc;                                    // Set relocation address
185
186                                 if (validsegment)
187                                         D_long(raddr);                               // Write relocation address
188
189                                 if (w & MPCREL)
190                                         rflag = 0x000000A0;                          // PC-relative fixup
191                                 else
192                                         rflag = 0x00000040;                          // Absolute fixup
193
194                                 if (w & MMOVEI)
195                                         rflag |= 0x00000001;
196                         }
197
198                         // Compute mark position in relocation information;
199                         // in RELMOD mode, get address of data to fix up.
200                         if (from == DATA)
201                                 loc += tsize;
202
203                         wp = (char *)(mp + loc);
204
205                         if (symbol)
206                         {
207                                 // Deposit external reference
208                                 if (obj_format == BSD)
209                                 {
210                                         rflag |= 0x00000010;                         // Set external reloc flag bit
211                                         rflag |= (symbol->senv << 8);                // Put symbol index in flags
212
213                                         if (symbol->sattre & RISCSYM)
214                                                 rflag |= 0x00000001;
215
216                                         if (validsegment)
217                                         {
218                                                 D_long(rflag);                            // Write relocation flags
219                                                 rsize += 8;                               // Increment relocation size
220                                         }
221                                 }
222                         }
223                         else
224                         {
225                                 if (obj_format == BSD)
226                                 {
227                                         w &= TDB;                                    // Set reloc flags to segment
228
229                                         switch (w)
230                                         {
231                                         case TEXT: rflag |= 0x00000400; break;
232                                         case DATA: rflag |= 0x00000600; break;
233                                         case BSS:  rflag |= 0x00000800; break;
234                                         }
235
236                                         if (validsegment)
237                                         {
238                                                 D_long(rflag);                            // Write relocation flags
239                                                 rsize += 8;                               // Increment relocation size
240                                         }
241
242                                         w &= TDB;
243
244                                         if (validsegment)
245                                         {
246                                                 if (w & (DATA|BSS))
247                                                 {
248                                                         dp = objimage + BSDHDRSIZE + loc;
249                                                         diff = ((LONG)(*dp++ & 0xFF)) << 24;
250                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 16;
251                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 8;
252                                                         diff |= (LONG)(*dp & 0xFF);
253                                                         DEBUG printf("diff=%ux ==> ", diff);
254         
255                                                         if (rflag & 0x01)
256                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
257
258                                                         diff += sect[TEXT].sloc;
259
260                                                         if (w == BSS)
261                                                                 diff += sect[DATA].sloc;
262
263                                                         if (rflag & 0x01)
264                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
265
266                                                         dp = objimage + BSDHDRSIZE + loc;
267                                                         *dp++ = (char)(diff >> 24);
268                                                         *dp++ = (char)(diff >> 16);
269                                                         *dp++ = (char)(diff >> 8);
270                                                         *dp = (char)diff;
271                                                         DEBUG printf("%ux\n", diff);
272                                                 }
273                                         }
274                                 }
275                         }
276                 }
277         }
278
279         // Return relocation size
280         if (obj_format == BSD)
281                 return rsize;                                        
282
283         return siz;
284 }