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