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