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