ELF support for RMAC.
[rmac] / sect.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // SECT.C - Code Generation, Fixups and Section Management
4 // Copyright (C) 199x Landon Dyer, 2017 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 "sect.h"
10 #include "direct.h"
11 #include "error.h"
12 #include "expr.h"
13 #include "listing.h"
14 #include "mach.h"
15 #include "mark.h"
16 #include "riscasm.h"
17 #include "symbol.h"
18 #include "token.h"
19
20
21 // Function prototypes
22 void MakeSection(int, uint16_t);
23 void SwitchSection(int);
24
25 // Section descriptors
26 SECT sect[NSECTS];              // All sections...
27 int cursect;                    // Current section number
28
29 // These are copied from the section descriptor, the current code chunk
30 // descriptor and the current fixup chunk descriptor when a switch is made into
31 // a section.  They are copied back to the descriptors when the section is left.
32 uint16_t scattr;                // Section attributes
33 uint32_t sloc;                  // Current loc in section
34
35 CHUNK * scode;                  // Current (last) code chunk
36 uint32_t challoc;               // # bytes alloc'd to code chunk
37 uint32_t ch_size;               // # bytes used in code chunk
38 uint8_t * chptr;                // Deposit point in code chunk buffer
39 uint8_t * chptr_opcode; // Backup of chptr, updated before entering code generators
40
41 CHUNK * sfix;                   // Current (last) fixup chunk
42 uint32_t fchalloc;              // # bytes alloc'd to fixup chunk
43 uint32_t fchsize;               // # bytes used in fixup chunk
44 PTR fchptr;                             // Deposit point in fixup chunk buffer
45
46 // Return a size (SIZB, SIZW, SIZL) or 0, depending on what kind of fixup is
47 // associated with a location.
48 static uint8_t fusiztab[] = {
49    0,   // FU_QUICK
50    1,   // FU_BYTE
51    2,   // FU_WORD
52    2,   // FU_WBYTE
53    4,   // FU_LONG
54    1,   // FU_BBRA
55    0,   // (unused)
56    1,   // FU_6BRA
57 };
58
59 // Offset to REAL fixup location
60 static uint8_t fusizoffs[] = {
61    0,   // FU_QUICK
62    0,   // FU_BYTE
63    0,   // FU_WORD
64    1,   // FU_WBYTE
65    0,   // FU_LONG
66    1,   // FU_BBRA
67    0,   // (unused)
68    0,   // FU_6BRA
69 };
70
71
72 //
73 // Initialize sections; setup initial ABS, TEXT, DATA and BSS sections
74 //
75 void InitSection(void)
76 {
77         int i;
78
79         // Cleanup all sections
80         for(i=0; i<NSECTS; i++)
81                 MakeSection(i, 0);
82
83         // Construct default sections, make TEXT the current section
84         MakeSection(ABS,  SUSED | SABS | SBSS);         // ABS
85         MakeSection(TEXT, SUSED | TEXT       );         // TEXT
86         MakeSection(DATA, SUSED | DATA       );         // DATA
87         MakeSection(BSS,  SUSED | BSS  | SBSS);         // BSS
88 //      MakeSection(M6502, SUSED | TEXT       );                // 6502 code section
89
90         // Switch to TEXT for starters
91         SwitchSection(TEXT);
92 }
93
94
95 //
96 // Make a new (clean) section
97 //
98 void MakeSection(int sno, uint16_t attr)
99 {
100         SECT * p = &sect[sno];
101         p->scattr = attr;
102         p->sloc = 0;
103         p->scode = p->sfcode = NULL;
104         p->sfix = p->sffix = NULL;
105 }
106
107
108 //
109 // Switch to another section (copy section & chunk descriptors to global vars
110 // for fast access)
111 //
112 void SwitchSection(int sno)
113 {
114         CHUNK * cp;
115         cursect = sno;
116         SECT * p = &sect[sno];
117
118         // Copy section vars
119         scattr = p->scattr;
120         sloc = p->sloc;
121         scode = p->scode;
122         sfix = p->sfix;
123
124         // Copy code chunk vars
125         if ((cp = scode) != NULL)
126         {
127                 challoc = cp->challoc;
128                 ch_size = cp->ch_size;
129                 chptr = cp->chptr + ch_size;
130         }
131         else
132                 challoc = ch_size = 0;
133
134         // Copy fixup chunk vars
135         if ((cp = sfix) != NULL)
136         {
137                 fchalloc = cp->challoc;
138                 fchsize = cp->ch_size;
139                 fchptr.cp = cp->chptr + fchsize;
140         }
141         else
142                 fchalloc = fchsize = 0;
143 }
144
145
146 //
147 // Save current section
148 //
149 void SaveSection(void)
150 {
151         SECT * p = &sect[cursect];
152
153         p->scattr = scattr;                                             // Bailout section vars
154         p->sloc = sloc;
155
156         if (scode != NULL)                                              // Bailout code chunk
157                 scode->ch_size = ch_size;
158
159         if (sfix != NULL)                                               // Bailout fixup chunk
160                 sfix->ch_size = fchsize;
161 }
162
163
164 //
165 // Test to see if a location has a fixup sic'd on it.  This is used by the
166 // listing generator to print 'xx's instead of '00's for forward references
167 //
168 int fixtest(int sno, uint32_t loc)
169 {
170         PTR fup;
171
172         // Force update to sect[] variables
173         StopMark();
174
175         // Hairy, ugly linear search for a mark on our location; the speed doesn't
176         // matter, since this is only done when generating a listing, which is
177         // SLOW.
178         for(CHUNK * ch=sect[sno].sffix; ch!=NULL; ch=ch->chnext)
179         {
180                 fup.cp = (uint8_t *)ch->chptr;
181                 uint8_t * fuend = fup.cp + ch->ch_size;
182
183                 while (fup.cp < fuend)
184                 {
185                         uint16_t w = *fup.wp++;
186                         uint32_t xloc = *fup.lp++ + (int)fusizoffs[w & FUMASK];
187                         fup.wp += 2;
188
189                         if (xloc == loc)
190                                 return (int)fusiztab[w & FUMASK];
191
192                         if (w & FU_EXPR)
193                         {
194                                 w = *fup.wp++;
195                                 fup.lp += w;
196                         }
197                         else
198                                 fup.lp++;
199                 }
200         }
201
202         return 0;
203 }
204
205
206 //
207 // Check that there are at least 'amt' bytes left in the current chunk. If
208 // there are not, allocate another chunk of at least 'amt' bytes (and probably
209 // more).
210 //
211 // If 'amt' is zero, ensure there are at least CH_THRESHOLD bytes, likewise.
212 //
213 int chcheck(uint32_t amt)
214 {
215         DEBUG { printf("chcheck(%u)\n", amt); }
216         // If in BSS section, no allocation required
217         if (scattr & SBSS)
218                 return 0;
219
220         if (!amt)
221                 amt = CH_THRESHOLD;
222
223         DEBUG { printf("    challoc=%i, ch_size=%i, diff=%i\n", challoc, ch_size, challoc-ch_size); }
224         if ((int)(challoc - ch_size) >= (int)amt)
225                 return 0;
226
227         if (amt < CH_CODE_SIZE)
228                 amt = CH_CODE_SIZE;
229
230         DEBUG { printf("    amt (adjusted)=%u\n", amt); }
231         SECT * p = &sect[cursect];
232         CHUNK * cp = malloc(sizeof(CHUNK) + amt);
233
234         // First chunk in section
235         if (scode == NULL)
236         {
237                 cp->chprev = NULL;
238                 p->sfcode = cp;
239         }
240         // Add chunk to other chunks
241         else
242         {
243                 cp->chprev = scode;
244                 scode->chnext = cp;
245                 scode->ch_size = ch_size;                       // Save old chunk's globals
246         }
247
248         // Setup chunk and global vars
249         cp->chloc = sloc;
250         cp->chnext = NULL;
251         challoc = cp->challoc = amt;
252         ch_size = cp->ch_size = 0;
253         chptr = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK);
254         scode = p->scode = cp;
255
256         return 0;
257 }
258
259
260 // This is really wrong. We need to make some proper structures here so we
261 // don't have to count sizes of objects, that's what the compiler's for! :-P
262 #define FIXUP_BASE_SIZE (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t))
263 //
264 // Arrange for a fixup on a location
265 //
266 int AddFixup(uint16_t attr, uint32_t loc, TOKEN * fexpr)
267 {
268         uint32_t i;
269         uint32_t len = 0;
270         CHUNK * cp;
271         SECT * p;
272         // Shamus: Expression lengths are voodoo ATM (variable "i"). Need to fix
273         //         this.
274 WARNING(!!! AddFixup() is filled with VOODOO !!!)
275         DEBUG printf("FIXUP@$%X: $%X\n", loc, attr);
276
277         // Compute length of expression (could be faster); determine if it's the
278         // single-symbol case; no expression if it's just a mark. This code assumes
279         // 16 bit WORDs and 32 bit LONGs
280         if (*fexpr == SYMBOL && fexpr[2] == ENDEXPR)
281         {
282                 // Just a single symbol
283                 // SCPCD : correct bit mask for attr (else other FU_xxx will match)
284                 // NYAN !
285                 if ((attr & FUMASKRISC) == FU_JR)
286                 {
287 //printf("AddFixup: ((attr & FUMASKRISC) == FU_JR)\n");
288 //                      i = 18;
289 //                      i = FIXUP_BASE_SIZE + (sizeof(uint32_t) * 2);
290                         i = FIXUP_BASE_SIZE + sizeof(SYM *) + sizeof(uint32_t);
291                 }
292                 else
293                 {
294 //printf("AddFixup: ((attr & FUMASKRISC) == FU_JR) ELSE\n");
295 //                      i = 14;
296                         i = FIXUP_BASE_SIZE + sizeof(SYM *);
297                 }
298         }
299         else
300         {
301 //printf("AddFixup: !SYMBOL\n");
302                 attr |= FU_EXPR;
303
304                 for(len=0; fexpr[len]!=ENDEXPR; len++)
305                 {
306                         if (fexpr[len] == CONST || fexpr[len] == SYMBOL)
307                                 len++;
308                 }
309
310                 len++;                                                          // Add 1 for ENDEXPR
311 //              i = (len << 2) + 12;
312                 i = FIXUP_BASE_SIZE + sizeof(uint16_t) + (len * sizeof(TOKEN));
313         }
314
315         // Alloc another fixup chunk for this one to fit in if necessary
316         if ((fchalloc - fchsize) < i)
317         {
318                 p = &sect[cursect];
319                 cp = (CHUNK *)malloc(sizeof(CHUNK) + CH_FIXUP_SIZE);
320
321                 // First fixup chunk in section
322                 if (sfix == NULL)
323                 {
324                         cp->chprev = NULL;
325                         p->sffix = cp;
326                 }
327                 // Add to other chunks
328                 else
329                 {
330                         cp->chprev = sfix;
331                         sfix->chnext = cp;
332                         sfix->ch_size = fchsize;
333                 }
334
335                 // Setup fixup chunk and its global vars
336                 cp->chnext = NULL;
337                 fchalloc = cp->challoc = CH_FIXUP_SIZE;
338                 fchsize = cp->ch_size = 0;
339                 fchptr.cp = cp->chptr = ((uint8_t *)cp) + sizeof(CHUNK);
340                 sfix = p->sfix = cp;
341         }
342
343         // Record fixup type, fixup location, and the file number and line number
344         // the fixup is located at.
345         *fchptr.wp++ = attr;
346         *fchptr.lp++ = loc;
347         *fchptr.wp++ = cfileno;
348         *fchptr.wp++ = (uint16_t)curlineno;
349
350         // Store postfix expression or pointer to a single symbol, or nothing for a
351         // mark.
352         if (attr & FU_EXPR)
353         {
354                 *fchptr.wp++ = (uint16_t)len;
355
356                 while (len--)
357                         *fchptr.lp++ = (uint32_t)*fexpr++;
358         }
359         else
360         {
361                 *fchptr.sy++ = symbolPtr[fexpr[1]];
362 //printf("AddFixup: adding symbol (%s) [%08X]\n", symbolPtr[fexpr[1]]->sname, symbolPtr[fexpr[1]]->sattr);
363         }
364
365         // SCPCD : correct bit mask for attr (else other FU_xxx will match) NYAN !
366         if ((attr & FUMASKRISC) == FU_JR)
367         {
368                 if (orgactive)
369                         *fchptr.lp++ = orgaddr;
370                 else
371                         *fchptr.lp++ = 0x00000000;
372         }
373
374         fchsize += i;
375         return 0;
376 }
377
378
379 //
380 // Resolve fixups in a section
381 //
382 int ResolveFixups(int sno)
383 {
384         PTR fup;                                // Current fixup
385         uint16_t * fuend;               // End of last fixup (in this chunk)
386         uint16_t w;                             // Fixup word (type+modes+flags)
387         uint8_t * locp;                 // Location to fix (in cached chunk)
388         uint32_t loc;                   // Location to fixup
389         VALUE eval;                             // Expression value
390         uint16_t eattr;                 // Expression attrib
391         SYM * esym;                             // External symbol involved in expr
392         SYM * sy;                               // (Temp) pointer to a symbol
393         uint16_t i;                             // (Temp) word
394         uint16_t tdb;                   // eattr & TDB
395         uint32_t oaddr;
396         int reg2;
397         uint16_t flags;
398
399         SECT * sc = &sect[sno];
400         CHUNK * ch = sc->sffix;
401
402         if (ch == NULL)
403                 return 0;
404
405         // "Cache" first chunk
406         CHUNK * cch = sc->sfcode;
407
408         // Can't fixup a section with nothing in it
409         if (cch == NULL)
410                 return 0;
411
412         do
413         {
414                 fup.cp = ch->chptr;                                     // fup -> start of chunk
415                 fuend = (uint16_t *)(fup.cp + ch->ch_size);     // fuend -> end of chunk
416
417                 while (fup.wp < fuend)
418                 {
419                         w = *fup.wp++;
420                         loc = *fup.lp++;
421                         cfileno = *fup.wp++;
422                         curlineno = (int)*fup.wp++;
423                         DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); }
424
425                         // This is based on global vars cfileno, curfname :-P
426                         // This approach is kinda meh as well. I think we can do better
427                         // than this.
428                         SetFilenameForErrorReporting();
429
430                         esym = NULL;
431
432                         // Search for chunk containing location to fix up; compute a
433                         // pointer to the location (in the chunk). Often we will find the
434                         // Fixup is in the "cached" chunk, so the linear-search is seldom
435                         // executed.
436                         if (loc < cch->chloc || loc >= (cch->chloc + cch->ch_size))
437                         {
438                                 for(cch=sc->sfcode; cch!=NULL; cch=cch->chnext)
439                                 {
440                                         if (loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
441                                                 break;
442                                 }
443
444                                 if (cch == NULL)
445                                 {
446                                         // Fixup (loc) out of range
447                                         interror(7);
448                                         // NOTREACHED
449                                 }
450                         }
451
452                         locp = cch->chptr + (loc - cch->chloc);
453                         eattr = 0;
454
455                         // Compute expression/symbol value and attribs
456
457                         // Complex expression
458                         if (w & FU_EXPR)
459                         {
460                                 i = *fup.wp++;
461
462                                 if (evexpr(fup.tk, &eval, &eattr, &esym) != OK)
463                                 {
464                                         fup.lp += i;
465                                         continue;
466                                 }
467
468                                 fup.lp += i;
469                         }
470                         // Simple symbol
471                         else
472                         {
473                                 sy = *fup.sy++;
474                                 eattr = sy->sattr;
475
476                                 if (eattr & DEFINED)
477                                         eval = sy->svalue;
478                                 else
479                                         eval = 0;
480
481                                 // If the symbol is not defined, but global, set esym to sy
482                                 if ((eattr & (GLOBAL | DEFINED)) == GLOBAL)
483                                         esym = sy;
484                         }
485
486                         tdb = (uint16_t)(eattr & TDB);
487
488                         // If the expression is undefined and no external symbol is
489                         // involved, then that's an error.
490                         if (!(eattr & DEFINED) && (esym == NULL))
491                         {
492                                 error(undef_error);
493                                 continue;
494                         }
495
496                         // Do the fixup
497                         //
498                         // If a PC-relative fixup is undefined, its value is *not*
499                         // subtracted from the location (that will happen in the linker
500                         // when the external reference is resolved).
501                         //
502                         // MWC expects PC-relative things to have the LOC subtracted from
503                         // the value, if the value is external (that is, undefined at this
504                         // point).
505                         //
506                         // PC-relative fixups must be DEFINED and either in the same
507                         // section (whereupon the subtraction takes place) or ABS (with no
508                         // subtract).
509                         if (w & FU_PCREL)
510                         {
511                                 if (eattr & DEFINED)
512                                 {
513                                         if (tdb == sno)
514                                                 eval -= (VALUE)loc;
515                                         else if (tdb)
516                                         {
517                                                 error("PC-relative expr across sections");
518                                                 continue;
519                                         }
520
521                                         if (sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
522                                                 warn("unoptimized short branch");
523                                 }
524                                 else if (obj_format == MWC)
525                                         eval -= (VALUE)loc;
526
527                                 tdb = 0;
528                                 eattr &= ~TDB;
529                         }
530
531                         // Do fixup classes
532                         switch ((int)(w & FUMASK))
533                         {
534                         // FU_BBRA fixes up a one-byte branch offset.
535                         case FU_BBRA:
536                                 if (!(eattr & DEFINED))
537                                 {
538                                         error("external short branch");
539                                         continue;
540                                 }
541
542                                 eval -= 2;
543
544                                 if (eval + 0x80 >= 0x100)
545                                         goto rangeErr;
546
547                                 if (eval == 0)
548                                 {
549                                         error("illegal bra.s with zero offset");
550                                         continue;
551                                 }
552
553                                 *++locp = (uint8_t)eval;
554                                 break;
555                         // Fixup one-byte value at locp + 1.
556                         case FU_WBYTE:
557                                 locp++;
558                                 // FALLTHROUGH
559                         // Fixup one-byte forward references
560                         case FU_BYTE:
561                                 if (!(eattr & DEFINED))
562                                 {
563                                         error("external byte reference");
564                                         continue;
565                                 }
566
567                                 if (tdb)
568                                 {
569                                         error("non-absolute byte reference");
570                                         continue;
571                                 }
572
573                                 if ((w & FU_PCREL) && eval + 0x80 >= 0x100)
574                                         goto rangeErr;
575
576                                 if (w & FU_SEXT)
577                                 {
578                                         if (eval + 0x100 >= 0x200)
579                                                 goto rangeErr;
580                                 }
581                                 else if (eval >= 0x100)
582                                         goto rangeErr;
583
584                                 *locp = (uint8_t)eval;
585                                 break;
586                         // Fixup WORD forward references;
587                         // the word could be unaligned in the section buffer, so we have to
588                         // be careful.
589                         case FU_WORD:
590                                 if ((w & FUMASKRISC) == FU_JR)
591                                 {
592                                         oaddr = *fup.lp++;
593
594                                         if (oaddr)
595                                                 reg2 = (signed)((eval - (oaddr + 2)) / 2);// & 0x1F;
596                                         else
597                                                 reg2 = (signed)((eval - (loc + 2)) / 2);// & 0x1F;
598
599                                         if ((reg2 < -16) || (reg2 > 15))
600                                         {
601                                                 error("relative jump out of range");
602                                                 break;
603                                         }
604
605                                         *locp = (uint8_t)(*locp | ((reg2 >> 3) & 0x03));
606                                         locp++;
607                                         *locp = (uint8_t)(*locp | ((reg2 & 0x07) << 5));
608                                         break;
609                                 }
610
611                                 if ((w & FUMASKRISC) == FU_NUM15)
612                                 {
613                                         if (eval < -16 || eval > 15)
614                                         {
615                                                 error("constant out of range");
616                                                 break;
617                                         }
618
619                                         *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
620                                         locp++;
621                                         *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
622                                         break;
623                                 }
624
625                                 if ((w & FUMASKRISC) == FU_NUM31)
626                                 {
627                                         if (eval < 0 || eval > 31)
628                                         {
629                                                 error("constant out of range");
630                                                 break;
631                                         }
632
633                                         *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
634                                         locp++;
635                                         *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
636                                         break;
637                                 }
638
639                                 if ((w & FUMASKRISC) == FU_NUM32)
640                                 {
641                                         if (eval < 1 || eval > 32)
642                                         {
643                                                 error("constant out of range");
644                                                 break;
645                                         }
646
647                                         if (w & FU_SUB32)
648                                                 eval = (32 - eval);
649
650                                         eval = (eval == 32) ? 0 : eval;
651                                         *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
652                                         locp++;
653                                         *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
654                                         break;
655                                 }
656
657                                 if ((w & FUMASKRISC) == FU_REGONE)
658                                 {
659                                         if (eval < 0 || eval > 31)
660                                         {
661                                                 error("register value out of range");
662                                                 break;
663                                         }
664
665                                         *locp = (uint8_t)(*locp | ((eval >> 3) & 0x03));
666                                         locp++;
667                                         *locp = (uint8_t)(*locp | ((eval & 0x07) << 5));
668                                         break;
669                                 }
670
671                                 if ((w & FUMASKRISC) == FU_REGTWO)
672                                 {
673                                         if (eval < 0 || eval > 31)
674                                         {
675                                                 error("register value out of range");
676                                                 break;
677                                         }
678
679                                         locp++;
680                                         *locp = (uint8_t)(*locp | (eval & 0x1F));
681                                         break;
682                                 }
683
684                                 if (!(eattr & DEFINED))
685                                 {
686                                         flags = MWORD;
687
688                                         if (w & FU_PCREL)
689                                                 flags |= MPCREL;
690
691                                         MarkRelocatable(sno, loc, 0, flags, esym);
692                                 }
693                                 else
694                                 {
695                                         if (tdb)
696                                                 MarkRelocatable(sno, loc, tdb, MWORD, NULL);
697
698                                         if (w & FU_SEXT)
699                                         {
700                                                 if (eval + 0x10000 >= 0x20000)
701                                                         goto rangeErr;
702                                         }
703                                         else
704                                         {
705                                                 // Range-check BRA and DBRA
706                                                 if (w & FU_ISBRA)
707                                                 {
708                                                         if (eval + 0x8000 >= 0x10000)
709                                                         goto rangeErr;
710                                                 }
711                                                 else if (eval >= 0x10000)
712                                                         goto rangeErr;
713                                         }
714                                 }
715
716                                 SETBE16(locp, 0, eval);
717                                 break;
718                         // Fixup LONG forward references;
719                         // the long could be unaligned in the section buffer, so be careful
720                         // (again).
721                         case FU_LONG:
722                                 flags = MLONG;
723
724                                 if ((w & FUMASKRISC) == FU_MOVEI)
725                                 {
726                                         // Long constant in MOVEI # is word-swapped, so fix it here
727                                         eval = WORDSWAP32(eval);
728                                         flags |= MMOVEI;
729                                 }
730
731                                 // If the symbol is undefined, make sure to pass the symbol in
732                                 // to the MarkRelocatable() function.
733                                 if (!(eattr & DEFINED))
734                                         MarkRelocatable(sno, loc, 0, flags, esym);
735                                 else if (tdb)
736                                         MarkRelocatable(sno, loc, tdb, flags, NULL);
737
738                                 SETBE32(locp, 0, eval);
739                                 break;
740
741                         // Fixup a 3-bit "QUICK" reference in bits 9..1
742                         // (range of 1..8) in a word. Really bits 1..3 in a byte.
743                         case FU_QUICK:
744                                 if (!(eattr & DEFINED))
745                                 {
746                                         error("External quick reference");
747                                         continue;
748                                 }
749
750                                 if (eval < 1 || eval > 8)
751                                         goto rangeErr;
752
753                                 *locp |= (eval & 7) << 1;
754                                 break;
755
756                         // Fix up 6502 funny branch
757                         case FU_6BRA:
758                                 eval -= (loc + 1);
759
760                                 if (eval + 0x80 >= 0x100)
761                                         goto rangeErr;
762
763                                 *locp = (uint8_t)eval;
764                                 break;
765
766                         default:
767                                 // Bad fixup type--this should *never* happen!
768                                 interror(4);
769                                 // NOTREACHED
770                         }
771                         continue;
772 rangeErr:
773                         error("expression out of range");
774                 }
775
776                 ch = ch->chnext;
777         }
778         while (ch != NULL);
779
780         return 0;
781 }
782
783 //
784 // Resolve all fixups
785 //
786 int ResolveAllFixups(void)
787 {
788         // Make undefined symbols GLOBL
789         if (glob_flag)
790                 ForceUndefinedSymbolsGlobal();
791
792         DEBUG printf("Resolving TEXT sections...\n");
793         ResolveFixups(TEXT);
794         DEBUG printf("Resolving DATA sections...\n");
795         ResolveFixups(DATA);
796
797         return 0;
798 }
799