A few compiler warnings pacified.
[rmac] / object.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // OBJECT.C - Writing Object Files
4 // Copyright (C) 199x Landon Dyer, 2011 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 "object.h"
10 #include "sect.h"
11 #include "symbol.h"
12 #include "mark.h"
13 #include "error.h"
14 #include "riscasm.h"
15
16 /*
17  *  Imports
18  */
19 extern int obj_format;          // object file format to write
20 extern int prg_flag;            // generate Atari ST direct executable
21
22 LONG symsize = 0;                       // Size of BSD symbol table
23 LONG strindx = 0x00000004;      // BSD string table index
24 char * strtable;                        // Pointer to the symbol string table
25 char * objImage;                        // Global object image pointer
26
27
28 //
29 // Add an entry to the BSD symbol table
30 //
31 char * constr_bsdsymtab(char * buf, SYM * sym, int globflag)
32 {
33         chptr = buf;                                            // Point to buffer for deposit longs
34         D_long(strindx);                                        // Deposit the symbol string index
35
36         WORD w1 = sym->sattr;                           // Obtain symbol attribute
37         int w2 = sym->sattre;
38         LONG z = 0;                                                     // Initialise resulting symbol flags
39
40         if (w1 & EQUATED)
41         {                                       
42                 z = 0x02000000;                                 // Set equated flag
43         }
44         else
45         {
46                 switch (w1 & TDB)
47                 {
48                 case TEXT: z = 0x04000000; break;       // Set TEXT segment flag
49                 case DATA: z = 0x06000000; break;       // Set DATA segment flag
50                 case BSS : z = 0x08000000; break;       // Set BSS segment flag
51                 }
52         }
53
54         if (globflag)
55                 z |= 0x01000000;                                // Set global flag if requested
56
57         D_long(z);                                                      // Deposit symbol attribute
58
59         z = sym->svalue;                                        // Obtain symbol value
60         w1 &= DATA | BSS;                                       // Determine DATA or BSS flag
61
62         if (w1)                                                   
63                 z += sect[TEXT].sloc;                   // If DATA or BSS add TEXT segment size
64
65         if (w1 & BSS) 
66                 z += sect[DATA].sloc;                   // If BSS add DATA segment size
67
68         D_long(z);                                                      // Deposit symbol value
69
70         strcpy(strtable + strindx, sym->sname);
71
72         strindx += strlen(sym->sname) + 1;      // Incr string index incl null terminate
73         buf += 12;                                                      // Increment buffer to next record
74         symsize += 12;                                          // Increment symbol table size
75
76         return buf;
77 }
78
79
80 /*
81  *  Alcyon symbol flags
82  */
83 #define AL_DEFINED      0x8000
84 #define AL_EQUATED      0x4000
85 #define AL_GLOBAL       0x2000
86 #define AL_EQUREG       0x1000
87 #define AL_EXTERN       0x0800
88 #define AL_DATA         0x0400
89 #define AL_TEXT         0x0200
90 #define AL_BSS          0x0100
91 #define AL_FILE         0x0080
92
93
94 static WORD tdb_tab[] = {
95         0,                              /* absolute */
96         AL_TEXT,                /* TEXT segment based */
97         AL_DATA, 0,             /* DATA segment based */
98         AL_BSS                  /* BSS segment based */
99 };
100
101
102 #define HDRSIZE 0x1C            /* size of Alcyon header */
103
104
105 /*
106  *  Add entry to symbol table;
107  *  if `globflag' is 1, make the symbol global;
108  *  if in .PRG mode, adjust symbol values for fake link.
109  *
110  */
111 char * constr_symtab(register char * buf, SYM * sym, int globflag)
112 {
113         register int i;
114         register char * s;
115         register WORD w;
116         register LONG z;
117         register WORD w1;
118
119         /*
120          *  Copy symbol name
121          */
122         s = sym->sname;
123
124         for(i=0; i<8 && *s; i++)
125                 *buf++ = *s++;
126
127         while (i++ < 8)
128                 *buf++ = '\0';
129
130         /*
131          *  Construct and deposit flag word
132          *
133          *      o  all symbols are AL_DEFINED
134          *      o  install T/D/B/A base
135          *    o  install 'equated'
136          *    o  commons (COMMON) are AL_EXTERN, but not BSS
137          *      o  exports (DEFINED) are AL_GLOBAL
138          *      o  imports (~DEFINED) are AL_EXTERN
139          *
140          */
141         w1 = sym->sattr;
142         w = AL_DEFINED | tdb_tab[w1 & TDB];
143
144         if (w1 & EQUATED)               /* equated */
145                 w |= AL_EQUATED;
146
147         if (w1 & COMMON)
148         {
149                 w |= AL_EXTERN | AL_GLOBAL;     /* common symbol */
150                 w &= ~AL_BSS;           /* they're not BSS in Alcyon object files */
151         }
152         else if (w1 & DEFINED)
153         {
154                 if (globflag)           /* export the symbol */
155                         w |= AL_GLOBAL;
156         }
157         else w |= AL_EXTERN;            /* imported symbol */
158
159         *buf++ = w >> 8;
160         *buf++ = (char)w;
161
162         z = sym->svalue;
163
164         if (prg_flag)                   /* relocate value in .PRG segment */
165         {
166                 w1 &= DATA | BSS;
167
168                 if (w1)
169                         z += sect[TEXT].sloc;
170
171                 if (w1 & BSS)
172                         z += sect[DATA].sloc;
173         }
174
175         *buf++ = z >> 24;               /* deposit symbol value */
176         *buf++ = z >> 16;
177         *buf++ = z >> 8;
178         *buf++ = z;
179
180         return buf;
181 }
182
183
184 //
185 // Write an object file to the passed in file descriptor
186 // N.B.: Return value is ignored...
187 //
188 int WriteObject(int fd)
189 {
190         LONG t;                                 // Scratch long
191         LONG tds;                               // TEXT & DATA segment size
192         int i;                                  // Temporary int
193         CHUNK * cp;                             // Chunk (for gather)
194         char * buf;                             // Scratch area
195         char * p;                               // Temporary ptr
196         LONG ssize;                             // Size of symbols
197         LONG trsize, drsize;    // Size of relocations
198         long unused;                    // For supressing 'write' warnings
199
200         // Write requested object file...
201         switch (obj_format)
202         {
203         case BSD:
204                 ssize = ((LONG)sy_assign(NULL, NULL));          // Assign index numbers to the symbols
205                 tds = sect[TEXT].sloc + sect[DATA].sloc;        // Get size of TEXT and DATA segment
206                 buf = malloc(0x600000);                                         // Allocate 6mb object file image memory
207
208                 if (buf == NULL)
209                 {
210                         error("cannot allocate object file memory (in BSD mode)");
211                         return ERROR;
212                 }
213
214                 memset(buf, 0, 0x600000);               // Reset allocated memory
215                 objImage = buf;                                 // Set global object image pointer
216                 strtable = malloc(0x200000);    // Allocate 2mb scratch buffer 
217
218                 if (strtable == NULL)
219                 {
220                         error("cannot allocate string table memory (in BSD mode)");
221                         return ERROR;
222                 }
223
224                 memset(strtable, 0, 0x200000);  // Reset allocated memory
225
226                 // Build object file header
227                 chptr = buf;                                    // Base of header
228                 D_long(0x00000107);                             // Magic number
229                 D_long(sect[TEXT].sloc);                // TEXT size 
230                 D_long(sect[DATA].sloc);                // DATA size 
231                 D_long(sect[BSS].sloc);                 // BSS size 
232                 D_long(0x00000000);                             // Symbol size
233                 D_long(0x00000000);                             // First entry (0L)
234                 D_long(0x00000000);                             // TEXT relocation size
235                 D_long(0x00000000);                             // BSD relocation size
236
237                 // Construct TEXT and DATA segments (without relocation changes)
238                 p = buf + BSDHDRSIZE;
239
240                 for(i=TEXT; i<=DATA; ++i)
241                 {
242                         for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
243                         {
244                                 memcpy(p, cp->chptr, cp->ch_size);
245                                 p += cp->ch_size;
246                         }
247                 }
248
249                 // Do relocation tables (and make changes to segment data)
250                 p = buf + (BSDHDRSIZE + tds);   // Move obj image ptr to reloc info
251                 trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table
252                 chptr = buf + 24;                               // Point to relocation hdr entry
253                 D_long(trsize);                                 // Write the relocation table size
254                 p = buf + (BSDHDRSIZE + tds + trsize);  // Move obj image ptr to reloc info
255                 drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table
256                 chptr = buf + 28;                               // Point to relocation hdr entry
257                 D_long(drsize);                                 // Write the relocation table size
258
259                 p = buf + (BSDHDRSIZE + tds + trsize + drsize);// Point to start of symbol table
260                 sy_assign(p, constr_bsdsymtab); // Build symbol and string tables
261                 chptr = buf + 16;                               // Point to sym table size hdr entry
262                 D_long(symsize);                                // Write the symbol table size
263
264                 // Point to string table
265                 p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize);    
266
267                 memcpy(p, strtable, strindx);   // Copy string table to object image
268
269                 if (buf)
270                         free(strtable);                         // Free allocated memory
271
272                 chptr = p;                                              // Point to string table size long
273                 D_long(strindx);                                // Write string table size
274
275                 // Write the BSD object file from the object image buffer
276                 unused = write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4);
277
278                 if (buf)
279                         free(buf);                                      // Free allocated memory
280
281                 break;
282
283         case ALCYON:
284                 /*
285                  *  Compute size of symbol table;
286                  *   assign numbers to the symbols...
287                  */
288                 ssize = 0;
289
290                 if (prg_flag != 1)
291                         ssize = ((LONG)sy_assign(NULL, NULL)) * 14;
292
293                 /*
294                  *  Alloc memory for header+text+data, symbol and
295                  *   relocation information construction.
296                  */
297                 t = tds = sect[TEXT].sloc + sect[DATA].sloc;
298
299                 if (t < ssize)
300                         t = ssize;
301
302                 buf = malloc((t + HDRSIZE) + HDRSIZE);
303
304                 /*
305                  *  Build object file header
306                  *   just before the text+data image
307                  */
308                 chptr = buf - HDRSIZE;  /* -> base of header */
309                 D_word(0x601a);                 /* magic number */
310                 t = sect[TEXT].sloc;    /* TEXT size */
311                 D_long(t);
312                 t = sect[DATA].sloc;    /* DATA size */
313                 D_long(t);
314                 t = sect[BSS].sloc;             /* BSS size */
315                 D_long(t);
316                 D_long(ssize);                  /* symbol table size */
317                 D_long(0);                              /* stack size (unused) */
318                 D_long(0);                              /* entry point (unused) */
319                 D_word(0);                              /* relocation information exists */
320
321                 /*
322                  *  Construct text and data segments;
323                  *  fixup relocatable longs in .PRG mode;
324                  *  finally write the header+text+data
325                  */
326                 p = buf;
327
328                 for(i=TEXT; i<=DATA; i++)
329                 {
330                         for (cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
331                         {
332                                 memcpy(p, cp->chptr, cp->ch_size);
333                                 p += cp->ch_size;
334                         }
335                 }
336
337                 if (prg_flag)
338                         markimg(buf, tds, sect[TEXT].sloc, 0);
339
340                 write(fd, buf - HDRSIZE, tds + HDRSIZE);
341
342                 /*
343                  *  Construct and write symbol table
344                  */
345                 if (prg_flag != 1)
346                 {
347                         sy_assign(buf, constr_symtab);
348                         write(fd, buf, ssize);
349                 }
350
351                 /*
352                  *  Construct and write relocation information;
353                  *   the size of it changes if we're writing a RELMODed executable.
354                  */
355                 tds = markimg(buf, tds, sect[TEXT].sloc, 1);
356                 write(fd, buf, tds);
357                 break;
358         }
359
360         return 0;
361 }
362