]> Shamusworld >> Repos - rmac/blob - mark.c
d3b827aede1bc00a44dae7080aebaeafa6ce47e5
[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 = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
97         p->mcnext = NULL;
98         p->mcalloc = MARK_ALLOC_INCR;
99         p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
100
101         if (curmch)
102         {                                             // Link onto previous chunk 
103                 *markptr.wp++ = MCHEND;                               // Mark end of block 
104                 curmch->mcused = mcused;
105                 curmch->mcnext = p;
106         }
107
108         if (!firstmch)
109                 firstmch = p;
110
111         curmch = p;                                              // Setup global vars 
112         markptr = p->mcptr;
113         mcalloc = MARK_ALLOC_INCR;
114         mcused = 0;
115
116         return 0;
117 }
118
119
120 //
121 // Make mark image for BSD .o file
122 //
123 LONG bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg)
124 {
125         MCHUNK * mch;                                             // Mark chunk
126         PTR p;                                                   // Source point from within mark chunk
127         WORD from;                                               // Section fixups are currently FROM
128         WORD w;                                                  // A word (temp)
129         LONG loc;                                                // Location (temp) 
130         SYM * symbol;                                             // Symbols (temp)
131         char * wp;                                                // Pointer into raw relocation info
132         char * dp;                                                // Deposit point for RELMOD info
133         LONG diff;                                               // Difference to relocate (RELMOD)
134         LONG raddr, rflag = 0;                                   // BSD relocation address and flags
135         LONG rsize;                                              // Relocation size
136         int validsegment = 0;                                    // Valid segment being processed
137
138         rsize = 0;                                               // Initialise relocation size
139         chptr = mp;
140
141         from = 0;
142         for(mch = firstmch; mch != NULL; mch = mch->mcnext)
143         {
144                 for(p=mch->mcptr;;)
145                 {
146                         w = *p.wp++;                                       // Next mark entry
147
148                         if (w & MCHEND)
149                                 break;                              // End of mark chunk
150
151                         // Get mark record
152                         symbol = NULL;
153                         loc = *p.lp++;                                     // Mark location
154
155                         if (w & MCHFROM)
156                         {                                  // Maybe change "from" section
157                                 from = *p.wp++;
158
159                                 if (obj_format == BSD)
160                                 {
161                                         if (reqseg == TEXT)
162                                         {                         // Requested segment is TEXT
163                                                 if (from == TEXT)
164                                                         validsegment = 1; 
165                                                 else
166                                                         validsegment = 0;
167                                         }
168                                         else
169                                         {                                     // Requested segment is DATA
170                                                 if (from == DATA)
171                                                         validsegment = 1; 
172                                                 else
173                                                         validsegment = 0;
174                                         }
175                                 }
176                         }
177
178                         if (w & MSYMBOL)                                    // Maybe includes a symbol
179                                 symbol = *p.sy++;
180
181                         if (obj_format == BSD)
182                         {
183                                 raddr = loc;                                    // Set relocation address
184
185                                 if (validsegment)
186                                         D_long(raddr);                               // Write relocation address
187
188                                 if (w & MPCREL)
189                                         rflag = 0x000000A0;                          // PC-relative fixup
190                                 else
191                                         rflag = 0x00000040;                          // Absolute fixup
192
193                                 if (w & MMOVEI)
194                                         rflag |= 0x00000001;
195                         }
196
197                         // Compute mark position in relocation information;
198                         // in RELMOD mode, get address of data to fix up.
199                         if (from == DATA)
200                                 loc += tsize;
201
202                         wp = (char *)(mp + loc);
203
204                         if (symbol)
205                         {
206                                 // Deposit external reference
207                                 if (obj_format == BSD)
208                                 {
209                                         rflag |= 0x00000010;                         // Set external reloc flag bit
210                                         rflag |= (symbol->senv << 8);                // Put symbol index in flags
211
212                                         if (symbol->sattre & RISCSYM)
213                                                 rflag |= 0x00000001;
214
215                                         if (validsegment)
216                                         {
217                                                 D_long(rflag);                            // Write relocation flags
218                                                 rsize += 8;                               // Increment relocation size
219                                         }
220                                 }
221                         }
222                         else
223                         {
224                                 if (obj_format == BSD)
225                                 {
226                                         w &= TDB;                                    // Set reloc flags to segment
227
228                                         switch (w)
229                                         {
230                                         case TEXT: rflag |= 0x00000400; break;
231                                         case DATA: rflag |= 0x00000600; break;
232                                         case BSS:  rflag |= 0x00000800; break;
233                                         }
234
235                                         if (validsegment)
236                                         {
237                                                 D_long(rflag);                            // Write relocation flags
238                                                 rsize += 8;                               // Increment relocation size
239                                         }
240
241                                         w &= TDB;
242
243                                         if (validsegment)
244                                         {
245                                                 if (w & (DATA|BSS))
246                                                 {
247                                                         dp = objimage + BSDHDRSIZE + loc;
248                                                         diff = ((LONG)(*dp++ & 0xFF)) << 24;
249                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 16;
250                                                         diff |= ((LONG)(*dp++ & 0xFF)) << 8;
251                                                         diff |= (LONG)(*dp & 0xFF);
252                                                         DEBUG printf("diff=%ux ==> ", diff);
253         
254                                                         if (rflag & 0x01)
255                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
256
257                                                         diff += sect[TEXT].sloc;
258
259                                                         if (w == BSS)
260                                                                 diff += sect[DATA].sloc;
261
262                                                         if (rflag & 0x01)
263                                                                 diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
264
265                                                         dp = objimage + BSDHDRSIZE + loc;
266                                                         *dp++ = (char)(diff >> 24);
267                                                         *dp++ = (char)(diff >> 16);
268                                                         *dp++ = (char)(diff >> 8);
269                                                         *dp = (char)diff;
270                                                         DEBUG printf("%ux\n", diff);
271                                                 }
272                                         }
273                                 }
274                         }
275                 }
276         }
277
278         // Return relocation size
279         if (obj_format == BSD)
280                 return rsize;                                        
281
282         return siz;
283 }