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