Version bump for last commit; now at v2.0.23.
[rmac] / mark.c
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // MARK.C - A record of things that are defined relative to any of the sections
4 // Copyright (C) 199x Landon Dyer, 2011-2020 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 #include "sect.h"
14
15
16 #define MARK_ALLOC_INCR 1024            // # bytes to alloc for more mark space
17 #define MIN_MARK_MEM    (3 * sizeof(uint16_t) + 1 * sizeof(uint32_t) + sizeof(SYM *))
18
19 MCHUNK * firstmch;              // First mark chunk
20 MCHUNK * curmch;                // Current mark chunk
21 PTR markptr;                    // Deposit point in current mark chunk
22 uint32_t mcalloc;               // # bytes alloc'd to current mark chunk
23 uint32_t mcused;                // # bytes used in current mark chunk
24 uint16_t curfrom;               // Current "from" section
25
26 // Table to convert from TDB to fixup triad
27 static uint8_t mark_tr[] = {
28         0,              // (N/A)
29         2,              // TEXT relocatable
30         1, 0,   // DATA relocatable
31         3               // BSS relocatable
32 };
33
34 //#define DEBUG_IMAGE_MARKING
35
36
37 //
38 // Initialize marker
39 //
40 void InitMark(void)
41 {
42         firstmch = curmch = NULL;
43         mcalloc = mcused = 0;
44         curfrom = 0;
45         sect[TEXT].relocs = sect[DATA].relocs = sect[BSS].relocs = 0;
46 }
47
48
49 //
50 // Wrap up marker (called after final mark is made)
51 //
52 void StopMark(void)
53 {
54         if (curmch)
55         {
56                 *markptr.wp = MCHEND;           // Mark end of block
57                 curmch->mcused = mcused;        // Update # used in mark block
58         }
59 }
60
61
62 //
63 // Mark a word or longword as relocatable
64 //
65 // Record is either 2, 3, or 4 pieces of data long. A mark is of the form:
66 // .W    <to+flags>     section mark is relative to, and flags in upper byte
67 // .L    <loc>          location of mark in "from" section
68 // .W    [from]         new from section (if different from current)
69 // .L    [symbol]       symbol involved in external reference (if any)
70 //
71 uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol)
72 {
73 #ifdef DEBUG_IMAGE_MARKING
74 printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=%p\n", section, loc, to, flags, symbol);
75 if (symbol)
76         printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%li, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
77 #endif
78
79         if ((mcalloc - mcused) < MIN_MARK_MEM)
80                 AllocateMark();
81
82         // Set up flags
83         flags |= to;
84
85         if (section != curfrom)
86                 flags |= MCHFROM;
87
88         if (symbol != NULL)
89                 flags |= MSYMBOL;
90
91         //
92         // Complain about some things are not allowed in '-p' (PRG) mode:
93         //  o  Marks that aren't to LONGs
94         //  o  External references
95         //
96         if (prg_flag)
97         {
98                 if (symbol != NULL)
99                         error("illegal external reference (in .PRG mode) to '%s'",
100                                 symbol->sname);
101         }
102
103         // Dump crap into the mark
104         *markptr.wp++ = flags;
105         *markptr.lp++ = loc;
106         mcused += sizeof(uint16_t) + sizeof(uint32_t);
107
108         if (flags & MCHFROM)
109         {
110                 curfrom = section;
111                 *markptr.wp++ = section;
112                 mcused += sizeof(uint16_t);
113         }
114
115         if (flags & MSYMBOL)
116         {
117                 *markptr.sy++ = symbol;
118                 mcused += sizeof(SYM *);
119         }
120
121         // Increment # of relocs in this section
122         sect[section].relocs++;
123
124         // Not sure what this is about (making sure the next mark is clear until
125         // it's marked as the end--I think)...
126         *markptr.wp = 0x0000;
127
128         return 0;
129 }
130
131
132 //
133 // Allocate another chunk of mark space
134 //
135 uint32_t AllocateMark(void)
136 {
137         // Alloc mark block header (and data) and set it up.
138         MCHUNK * p = malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
139         p->mcnext = NULL;
140         p->mcalloc = MARK_ALLOC_INCR;
141         p->mcptr.cp = (uint8_t *)p + sizeof(MCHUNK);
142         p->mcused = 0;
143
144         if (firstmch == NULL)
145                 firstmch = p;
146
147         if (curmch)
148         {
149                 // Link onto previous chunk
150                 *markptr.wp++ = MCHEND;         // Mark end of block
151                 curmch->mcused = mcused;
152                 curmch->mcnext = p;
153         }
154
155         // Setup global vars
156         curmch = p;
157         markptr = p->mcptr;
158         mcalloc = MARK_ALLOC_INCR;
159         mcused = 0;
160
161         return 0;
162 }
163
164
165 //
166 // Make mark image for Alcyon .o file
167 // okflag: 1, ok to deposit reloc information
168 //
169 uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag)
170 {
171         uint16_t from = 0;              // Section fixups are currently FROM
172         uint32_t loc;                   // Location (temp)
173         uint32_t lastloc;               // Last location fixed up (RELMOD)
174         uint8_t * wp;                   // Pointer into raw relocation information
175         register uint8_t * dp;  // Deposit point for RELMOD information
176
177         if (okflag)
178                 memset(mp, 0, siz);             // zero relocation buffer
179
180         for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
181         {
182                 for(PTR p=mch->mcptr;;)
183                 {
184                         uint16_t w = *p.wp++;// w = next mark entry
185
186                         if (w & MCHEND)         // (end of mark chunk)
187                                 break;
188
189                         // Get mark record
190                         SYM * symbol = NULL;
191                         loc = *p.lp++;          // mark location
192
193                         if (w & MCHFROM)        // maybe change "from" section
194                                 from = *p.wp++;
195
196                         if (w & MSYMBOL)        // maybe includes a symbol
197                                 symbol = *p.sy++;
198
199                         // Compute mark position in relocation information; in RELMOD mode,
200                         // get address of data to fix up.
201                         if (from == DATA)
202                                 loc += tsize;
203
204                         wp = (uint8_t *)(mp + loc);
205
206                         if (okflag && (w & MLONG)) // indicate first word of long
207                         {
208                                 wp[1] = 5;
209                                 wp += 2;
210                         }
211
212                         if (symbol)
213                         {
214                                 // Deposit external reference
215                                 if (okflag)
216                                 {
217                                         if (w & MPCREL)
218                                                 w = 6;          // PC-relative fixup
219                                         else
220                                                 w = 4;          // Absolute fixup
221
222                                         w |= symbol->senv << 3;
223                                         *wp++ = w >> 8;
224                                         *wp = (uint8_t)w;
225                                 }
226                         }
227                         else
228                         {
229                                 // Deposit section-relative mark; in RELMOD mode, fix it up in
230                                 // the chunk, kind of like a sleazoid linker.
231                                 //
232                                 // In RELMOD mode, marks to words (MWORDs) "cannot happen,"
233                                 // checks are made when mark() is called, so we don't have to
234                                 // check again here.
235                                 w &= TDB;
236
237                                 if (okflag)
238                                         wp[1] = mark_tr[w];
239                                 else if (prg_flag && (w & (DATA | BSS)))
240                                 {
241                                         uint32_t diff = GETBE32(wp, 0);
242 #ifdef DO_DEBUG
243                                         DEBUG printf("diff=%lx ==> ", diff);
244 #endif
245                                         diff += sect[TEXT].sloc;
246
247                                         if (w == BSS)
248                                                 diff += sect[DATA].sloc;
249
250                                         SETBE32(wp, 0, diff)
251 #ifdef DO_DEBUG
252                                         DEBUG printf("%lx\n", diff);
253 #endif
254                                 }
255                         }
256                 }
257         }
258
259         // Generate ".PRG" relocation information in place in the relocation words
260         // (the "RELMOD" operation).
261         if (okflag && prg_flag)
262         {
263                 int firstp = 1;
264                 wp = dp = mp;
265
266                 for(loc=0; loc<siz;)
267                 {
268                         if ((wp[1] & 7) == 5)
269                         {
270                                 if (firstp)
271                                 {
272                                         SETBE32(dp, 0, loc);
273                                         dp += 4;
274                                         firstp = 0;
275                                 }
276                                 else
277                                 {
278                                         uint32_t diff;
279
280                                         for(diff=loc-lastloc; diff>254; diff-=254)
281                                                 *dp++ = 1;
282
283                                         *dp++ = (uint8_t)diff;
284                                 }
285
286                                 lastloc = loc;
287                                 loc += 4;
288                                 wp += 4;
289                         }
290                         else
291                         {
292                                 loc += 2;
293                                 wp += 2;
294                         }
295                 }
296
297                 // Terminate relocation list with 0L (if there was no relocation) or
298                 // 0.B (if relocation information was written).
299                 if (!firstp)
300                         *dp++ = 0;
301                 else
302                         for(firstp=0; firstp<4; firstp++)
303                                 *dp++ = 0;
304
305                 // Return size of relocation information
306                 loc = dp - mp;
307                 return loc;
308         }
309
310         return siz;
311 }
312
313
314 //
315 // Make mark image for BSD .o file
316 //
317 // Assumptions about mark records (for BSD): if there is a symbol, the mark is
318 // for an undefined symbol, otherwise it's just a normal TDB relocation.
319 // N.B.: tsize is only used if reqseg is DATA
320 //
321 uint32_t MarkBSDImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg)
322 {
323         uint16_t from = 0;                      // Section fixups are currently FROM
324         uint32_t rsize = 0;                     // Relocation table size (written to mp)
325         int validsegment = 0;           // We are not yet in a valid segment...
326
327 #ifdef DEBUG_IMAGE_MARKING
328 printf("MarkBSDImage():\n");
329 #endif
330         // Initialize relocation table point (for D_foo macros)
331         chptr = mp;
332
333         // Run through all the relocation mark chunks
334         for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
335         {
336                 for(PTR p=mch->mcptr;;)
337                 {
338                         SYM * symbol = NULL;
339                         uint16_t w = *p.wp++;   // Next mark entry
340
341                         // If we hit the end of a chunk, go get the next one
342                         if (w & MCHEND)
343                                 break;
344
345                         // Get the rest of the mark record
346                         uint32_t loc = *p.lp++; // Mark location
347
348                         // Maybe change "from" section
349                         if (w & MCHFROM)
350                         {
351                                 from = *p.wp++;
352
353                                 if (((reqseg == TEXT) && (from == TEXT))
354                                         || ((reqseg == DATA) && (from == DATA)))
355                                         validsegment = 1;
356                                 else
357                                         validsegment = 0;
358                         }
359
360                         // Maybe includes a symbol
361                         if (w & MSYMBOL)
362                                 symbol = *p.sy++;
363
364                         if (!validsegment)
365                                 continue;
366
367 #ifdef DEBUG_IMAGE_MARKING
368 printf(" validsegment: raddr = $%08X\n", loc);
369 #endif
370                         uint32_t rflag = 0x00000040;    // Absolute relocation
371
372                         if (w & MPCREL)
373                                 rflag = 0x000000A0;                     // PC-relative relocation
374
375                         // This flag tells the linker to WORD swap the LONG when doing the
376                         // relocation.
377                         if (w & MMOVEI)
378                                 rflag |= 0x00000001;
379
380                         // This tells the linker to do a WORD relocation (otherwise it
381                         // defaults to doing a LONG, throwing things off for WORD sized
382                         // fixups)
383                         if (!(w & (MLONG | MQUAD)))
384                                 rflag |= 0x00000002;
385
386                         // Tell the linker that the fixup is an OL QUAD data address
387                         if (w & MQUAD)
388                                 rflag |= 0x00000004;
389
390                         if (symbol != NULL)
391                         {
392                                 // Deposit external reference
393                                 rflag |= 0x00000010;                    // Set external reloc flag bit
394                                 rflag |= (symbol->senv << 8);   // Put symbol index in flags
395
396 #ifdef DEBUG_IMAGE_MARKING
397 printf("  validsegment(2): rflag = $%08X\n", rflag);
398 #endif
399                         }
400                         else
401                         {
402 #ifdef DEBUG_IMAGE_MARKING
403 printf("  w = $%04X\n", w);
404 #endif
405                                 w &= TDB;                               // Set reloc flags to segment
406
407                                 switch (w)
408                                 {
409                                 case TEXT: rflag |= 0x00000400; break;
410                                 case DATA: rflag |= 0x00000600; break;
411                                 case BSS:  rflag |= 0x00000800; break;
412                                 }
413
414 #ifdef DEBUG_IMAGE_MARKING
415 printf("  validsegment(3): rflag = $%08X\n", rflag);
416 #endif
417                                 // Fix relocation by adding in start of TEXT segment, since it's
418                                 // currently relative to the start of the DATA (or BSS) segment
419                                 if (w & (DATA | BSS))
420                                 {
421                                         uint8_t * dp = objImage + BSDHDRSIZE + loc;
422                                         uint32_t olBitsSave = 0;
423
424                                         // Bump the start of the section if it's DATA (& not TEXT)
425                                         if (from == DATA)
426                                                 dp += tsize;
427
428                                         uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
429
430                                         // Special handling for OP (data addr) relocation...
431                                         if (rflag & 0x04)
432                                         {
433                                                 olBitsSave = diff & 0x7FF;
434                                                 diff = (diff & 0xFFFFF800) >> 8;
435                                         }
436
437                                         DEBUG printf("diff=%uX ==> ", diff);
438 #ifdef DEBUG_IMAGE_MARKING
439 printf("  validsegment(4): diff = $%08X ", diff);
440 #endif
441                                         if (rflag & 0x01)
442                                                 diff = WORDSWAP32(diff);
443
444 #ifdef DEBUG_IMAGE_MARKING
445 printf("(sect[TEXT].sloc=$%X) --> ", sect[TEXT].sloc);
446 #endif
447                                         diff += sect[TEXT].sloc;
448
449                                         if (w == BSS)
450                                                 diff += sect[DATA].sloc;
451
452                                         if (rflag & 0x01)
453                                                 diff = WORDSWAP32(diff);
454
455                                         // Make sure to deposit the correct size payload
456                                         // N.B.: The braces around the SETBExx macros are needed
457                                         //       because the macro supplies its own set of braces,
458                                         //       thus leaving a naked semicolon afterwards to
459                                         //       screw up the if/else structure. This is the price
460                                         //       you pay when using macros pretending to be code.
461                                         if (rflag & 0x02)               // WORD relocation
462                                         {
463                                                 SETBE16(dp, 0, diff);
464                                         }
465                                         else if (rflag & 0x04)  // OP data address relocation
466                                         {
467                                                 // We do it this way because we might have an offset
468                                                 // that is not a multiple of 8 and thus we need this in
469                                                 // place to prevent a bad address at link time. :-P As
470                                                 // a consequence of this, the highest address we can
471                                                 // have here is $1FFFF8.
472                                                 uint32_t diffsave = diff;
473                                                 diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
474                                                 SETBE32(dp, 0, diff);
475                                                 // But we need those 3 bits, otherwise we can get in
476                                                 // trouble with things like OL data that is in the cart
477                                                 // space, and BOOM! So the 2nd phrase of the fixup (it
478                                                 // will *always* have a 2nd phrase) has a few spare
479                                                 // bits, we chuck them in there.
480                                                 uint32_t p2 = GETBE32(dp, 8);
481                                                 p2 &= 0x1FFFFFFF;
482                                                 p2 |= (diffsave & 0x00E00000) << 8;
483                                                 SETBE32(dp, 8, p2);
484                                         }
485                                         else                                    // LONG relocation
486                                         {
487                                                 SETBE32(dp, 0, diff);
488                                         }
489
490                                         DEBUG printf("%uX\n", diff);
491 #ifdef DEBUG_IMAGE_MARKING
492 printf("$%08X\n", diff);
493 #endif
494                                 }
495                         }
496
497                         D_long(loc);            // Write relocation address
498                         D_long(rflag);          // Write relocation flags
499                         rsize += 0x08;          // Increment relocation size
500                 }
501         }
502
503         // Return relocation table's size
504 #ifdef DEBUG_IMAGE_MARKING
505 printf("  rsize = $%X\n", rsize);
506 #endif
507         return rsize;
508 }
509
510
511 //
512 // Make mark image for RAW file
513 //
514 uint32_t MarkABSImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg)
515 {
516         uint16_t from = 0;                      // Section fixups are currently FROM
517         uint32_t rsize = 0;                     // Relocation table size (written to mp)
518         int validsegment = 0;           // We are not yet in a valid segment...
519
520         // Initialize relocation table point (for D_foo macros)
521         chptr = mp;
522
523         // Run through all the relocation mark chunks
524         for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
525         {
526                 for (PTR p = mch->mcptr;;)
527                 {
528                         SYM * symbol = NULL;
529                         uint16_t w = *p.wp++;   // Next mark entry
530
531                         // If we hit the end of a chunk, go get the next one
532                         if (w & MCHEND)
533                                 break;
534
535                         // Get the rest of the mark record
536                         uint32_t loc = *p.lp++; // Mark location
537
538                         // Maybe change "from" section
539                         if (w & MCHFROM)
540                         {
541                                 from = *p.wp++;
542
543                                 if (((reqseg == TEXT) && (from == TEXT))
544                                 || ((reqseg == DATA) && (from == DATA)))
545                                         validsegment = 1;
546                                 else
547                                         validsegment = 0;
548                         }
549
550                         // Maybe includes a symbol
551                         if (w & MSYMBOL)
552                                 symbol = *p.sy++;
553
554                         if (!validsegment)
555                                 continue;
556
557                         uint32_t rflag = 0x00000040;    // Absolute relocation
558
559                         if (w & MPCREL)
560                                 rflag = 0x000000A0;                     // PC-relative relocation
561
562                         // This flag tells the linker to WORD swap the LONG when doing the
563                         // relocation.
564                         if (w & MMOVEI)
565                                 rflag |= 0x00000001;
566
567                         // This tells the linker to do a WORD relocation (otherwise it
568                         // defaults to doing a LONG, throwing things off for WORD sized
569                         // fixups)
570                         if (!(w & (MLONG | MQUAD)))
571                                 rflag |= 0x00000002;
572
573                         // Tell the linker that the fixup is an OL QUAD data address
574                         if (w & MQUAD)
575                                 rflag |= 0x00000004;
576
577                         if (symbol != NULL)
578                         {
579                                 return error("Unresolved symbol when outputting raw image");
580                         }
581                         else
582                         {
583                                 w &= TDB;                               // Set reloc flags to segment
584
585                                 switch (w)
586                                 {
587                                 case TEXT: rflag |= 0x00000400; break;
588                                 case DATA: rflag |= 0x00000600; break;
589                                 case BSS:  rflag |= 0x00000800; break;
590                                 }
591
592                                 // Fix relocation by adding in start of TEXT segment, since it's
593                                 // currently relative to the start of the DATA (or BSS) segment
594                                 uint8_t * dp = objImage + loc;
595                                 uint32_t olBitsSave = 0;
596
597                                 // Bump the start of the section if it's DATA (& not TEXT)
598                                 if (from == DATA)
599                                         dp += tsize;
600
601                                 uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
602
603                                 if (w & (DATA | BSS))
604                                 {
605                                         // Special handling for OP (data addr) relocation...
606                                         if (rflag & 0x04)
607                                         {
608                                                 olBitsSave = diff & 0x7FF;
609                                                 diff = (diff & 0xFFFFF800) >> 8;
610                                         }
611
612                                         if (rflag & 0x01)
613                                                 diff = WORDSWAP32(diff);
614
615                                         diff += sect[TEXT].sloc;
616
617                                         if (w == BSS)
618                                                 diff += sect[DATA].sloc;
619                                 }
620                                 if ((rflag & 0x02) == 0)
621                                 {
622                                         diff += org68k_address;
623                                 }
624
625                                 if (rflag & 0x01)
626                                         diff = WORDSWAP32(diff);
627                 
628                                 // Make sure to deposit the correct size payload
629                                 // Check comments in MarkBSDImage for more candid moments
630                                 if (rflag & 0x02)               // WORD relocation
631                                 {
632                                         SETBE16(dp, 0, diff);
633                                 }
634                                 else if (rflag & 0x04)  // OP data address relocation
635                                 {
636                                         // We do it this way because we might have an offset
637                                         // that is not a multiple of 8 and thus we need this in
638                                         // place to prevent a bad address at link time. :-P As
639                                         // a consequence of this, the highest address we can
640                                         // have here is $1FFFF8.
641                                         uint32_t diffsave = diff;
642                                         diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
643                                         SETBE32(dp, 0, diff);
644                                         // But we need those 3 bits, otherwise we can get in
645                                         // trouble with things like OL data that is in the cart
646                                         // space, and BOOM! So the 2nd phrase of the fixup (it
647                                         // will *always* have a 2nd phrase) has a few spare
648                                         // bits, we chuck them in there.
649                                         uint32_t p2 = GETBE32(dp, 8);
650                                         p2 &= 0x1FFFFFFF;
651                                         p2 |= (diffsave & 0x00E00000) << 8;
652                                         SETBE32(dp, 8, p2);
653                                 }
654                                 else                                    // LONG relocation
655                                 {
656                                         SETBE32(dp, 0, diff);
657                                 }
658                         }
659                 }
660         }
661
662         return OK;
663 }
664
665
666 //
667 // Make relocation record for ELF .o file.
668 // Returns the size of the relocation record.
669 //
670 uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t section)
671 {
672         uint16_t from = 0;              // Section fixups are currently FROM
673         uint32_t rsize = 0;             // Size of the relocation table
674
675         // Setup pointer for D_long/word/byte macros
676         chptr = buf;
677         ch_size = 0;
678
679         for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
680         {
681                 for(register PTR p=mch->mcptr;;)
682                 {
683                         register uint16_t w = *p.wp++;  // w = next mark entry
684
685                         if (w & MCHEND)         // (end of mark chunk)
686                                 break;
687
688                         // Get mark record
689                         SYM * symbol = NULL;
690                         uint16_t symFlags = 0;
691                         uint32_t r_offset = *p.lp++;    // Mark's location
692
693                         if (w & MCHFROM)                // Maybe change "from" section
694                                 from = *p.wp++;
695
696                         if (w & MSYMBOL)                // Maybe includes a symbol
697                         {
698                                 symbol = *p.sy++;
699
700                                 if (symbol)
701                                         symFlags = symbol->sattr;
702                         }
703
704                         // Create relocation record for ELF object, if the mark is in the
705                         // current section.
706                         if (from & section)
707                         {
708                                 uint32_t r_sym = 0;
709                                 uint32_t r_type = 0;
710                                 uint32_t r_addend = 0;
711
712                                 // Since we're chucking all symbols here for ELF objects by
713                                 // default (cf. sect.c), we discriminate here (normally, if
714                                 // there is a symbol in the mark record, it means an undefined
715                                 // symbol) :-P
716                                 if (symbol && !(symFlags & DEFINED) && (symFlags & GLOBAL))
717                                         r_sym = symbol->senv + extraSyms;
718                                 else if (w & TEXT)
719                                         r_sym = elfHdrNum[ES_TEXT];     // Mark TEXT segment
720                                 else if (w & DATA)
721                                         r_sym = elfHdrNum[ES_DATA];     // Mark DATA segment
722                                 else if (w & BSS)
723                                         r_sym = elfHdrNum[ES_BSS];      // Mark BSS segment
724
725                                 // Set the relocation type next
726                                 if (w & MPCREL)
727                                         r_type = 5;  // R_68K_PC16
728                                 // N.B.: Since we've established that (from & section) is non-
729                                 //       zero, this condition will *never* be satisfied... :-P
730                                 //       It might be better to check the symbol's senv; that is,
731                                 //       if this is a real problem that needs addressing...
732                                 else if ((from & section) == 0)
733                                         // In the case of a section referring to a label in another
734                                         // section (for example text->data) use a R_68K_PC32 mark.
735                                         r_type = 4;  // R_68K_PC32
736                                 else
737                                         r_type = 1;  // R_68K_32
738
739                                 r_addend = GETBE32(secBuf + r_offset, 0);
740
741                                 // Deposit the relocation record
742                                 D_long(r_offset);
743                                 D_long(((r_sym << 8) | r_type));
744                                 D_long(r_addend);
745                                 rsize += 0x0C;
746                         }
747                 }
748         }
749
750         return rsize;
751 }
752