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