]> Shamusworld >> Repos - rmac/blob - sect.c
64ccb441b759cb6f212fc96faf5210bbc4ee045e
[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, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "sect.h"
10 #include "direct.h"
11 #include "error.h"
12 #include "expr.h"
13 #include "listing.h"
14 #include "mach.h"
15 #include "mark.h"
16 #include "riscasm.h"
17 #include "symbol.h"
18 #include "token.h"
19
20
21 // Function prototypes
22 void MakeSection(int, WORD);
23 void SwitchSection(int);
24
25 // Section descriptors
26 SECT sect[NSECTS];              // All sections... 
27 int cursect;                    // Current section number
28
29 // These are copied from the section descriptor, the current code chunk
30 // descriptor and the current fixup chunk descriptor when a switch is made into
31 // a section.  They are copied back to the descriptors when the section is left.
32 WORD scattr;                    // Section attributes 
33 LONG sloc;                              // Current loc in section 
34
35 CHUNK * scode;                  // Current (last) code chunk 
36 LONG challoc;                   // # bytes alloc'd to code chunk 
37 LONG ch_size;                   // # bytes used in code chunk 
38 char * chptr;                   // Deposit point in code chunk buffer 
39
40 CHUNK * sfix;                   // Current (last) fixup chunk
41 LONG fchalloc;                  // # bytes alloc'd to fixup chunk
42 LONG fchsize;                   // # bytes used in fixup chunk
43 PTR fchptr;                             // Deposit point in fixup chunk buffer
44
45 // Return a size (SIZB, SIZW, SIZL) or 0, depending on what kind of fixup is
46 // associated with a location.
47 static char fusiztab[] = {
48    0,   // FU_QUICK
49    1,   // FU_BYTE
50    2,   // FU_WORD
51    2,   // FU_WBYTE
52    4,   // FU_LONG
53    1,   // FU_BBRA
54    0,   // (unused)
55    1,   // FU_6BRA
56 };
57
58 // Offset to REAL fixup location
59 static char fusizoffs[] = {
60    0,   // FU_QUICK
61    0,   // FU_BYTE
62    0,   // FU_WORD
63    1,   // FU_WBYTE
64    0,   // FU_LONG
65    1,   // FU_BBRA
66    0,   // (unused)
67    0,   // FU_6BRA
68 };
69
70
71 //
72 // Initialize sections; setup initial ABS, TEXT, DATA and BSS sections
73 //
74 void InitSection(void)
75 {
76         int i;
77
78         // Cleanup all sections
79         for(i=0; i<NSECTS; i++)
80                 MakeSection(i, 0);
81
82         // Construct default sections, make TEXT the current section
83         MakeSection(ABS,  SUSED | SABS | SBSS);         // ABS
84         MakeSection(TEXT, SUSED | TEXT       );         // TEXT
85         MakeSection(DATA, SUSED | DATA       );         // DATA
86         MakeSection(BSS,  SUSED | BSS  | SBSS);         // BSS
87 //      MakeSection(M6502, SUSED | TEXT       );                // 6502 code section
88
89         // Switch to TEXT for starters
90         SwitchSection(TEXT);
91 }
92
93
94 //
95 // Make a new (clean) section
96 //
97 void MakeSection(int sno, WORD attr)
98 {
99         SECT * p = &sect[sno];
100         p->scattr = attr;
101         p->sloc = 0;
102         p->scode = p->sfcode = NULL;
103         p->sfix = p->sffix = NULL;
104 }
105
106
107 //
108 // Switch to another section (copy section & chunk descriptors to global vars
109 // for fast access)
110 //
111 void SwitchSection(int sno)
112 {
113         CHUNK * cp;
114         cursect = sno;
115         SECT * p = &sect[sno];
116
117         // Copy section vars
118         scattr = p->scattr;
119         sloc = p->sloc;
120         scode = p->scode;
121         sfix = p->sfix;
122
123         // Copy code chunk vars
124         if ((cp = scode) != NULL)
125         {
126                 challoc = cp->challoc;
127                 ch_size = cp->ch_size;
128                 chptr = cp->chptr + ch_size;
129         }
130         else
131                 challoc = ch_size = 0;
132
133         // Copy fixup chunk vars 
134         if ((cp = sfix) != NULL)
135         {
136                 fchalloc = cp->challoc;
137                 fchsize = cp->ch_size;
138                 fchptr.cp = cp->chptr + fchsize;
139         }
140         else
141                 fchalloc = fchsize = 0;
142 }
143
144
145 //
146 // Save current section
147 //
148 void SaveSection(void)
149 {
150         SECT * p = &sect[cursect];
151
152         p->scattr = scattr;                                             // Bailout section vars
153         p->sloc = sloc;
154
155         if (scode != NULL)                                              // Bailout code chunk
156                 scode->ch_size = ch_size;
157
158         if (sfix != NULL)                                               // Bailout fixup chunk
159                 sfix->ch_size = fchsize;
160 }
161
162
163 //
164 // Test to see if a location has a fixup sic'd on it.  This is used by the
165 // listing generator to print 'xx's instead of '00's for forward references
166 //
167 int fixtest(int sno, LONG loc)
168 {
169         CHUNK * ch;
170         PTR fup;
171         char * fuend;
172         WORD w;
173         LONG xloc;
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(ch=sect[sno].sffix; ch!=NULL; ch=ch->chnext)
182         {
183                 fup.cp = (char *)ch->chptr;
184                 fuend = fup.cp + ch->ch_size;
185
186                 while (fup.cp < fuend)
187                 {
188                         w = *fup.wp++;
189                         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(LONG 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 = ((char *)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(WORD) + sizeof(LONG) + sizeof(WORD) + sizeof(WORD))
266 //
267 // Arrange for a fixup on a location
268 //
269 int AddFixup(WORD attr, LONG loc, TOKEN * fexpr)
270 {
271         LONG i;
272         LONG len = 0;
273         CHUNK * cp;
274         SECT * p;
275         // Shamus: Expression lengths are voodoo ATM (variable "i"). Need to fix
276         //         this.
277 #ifndef _MSC_VER
278 #pragma warning "!!! AddFixup() is filled with VOODOO !!!"
279 #else
280 #pragma WARNING(!!! AddFixup() is filled with VOODOO !!!)
281 #endif
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(LONG) * 2);
297                         i = FIXUP_BASE_SIZE + sizeof(SYM *) + sizeof(LONG);
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(WORD) + (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 = ((char *)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++ = (WORD)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++ = (WORD)len;
362
363                 while (len--)
364                         *fchptr.lp++ = (LONG)*fexpr++;
365         }
366         else
367         {
368 //              *fchptr.lp++ = (LONG)fexpr[1];
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         WORD * fuend;                   // End of last fixup (in this chunk)
394         WORD w;                                 // Fixup word (type+modes+flags)
395         char * locp;                    // Location to fix (in cached chunk) 
396         LONG loc;                               // Location to fixup
397         VALUE eval;                             // Expression value 
398         WORD eattr;                             // Expression attrib
399         SYM * esym;                             // External symbol involved in expr
400         SYM * sy;                               // (Temp) pointer to a symbol
401         WORD i;                                 // (Temp) word
402         WORD tdb;                               // eattr & TDB
403         LONG oaddr;
404         int reg2;
405         WORD flags;
406         unsigned page_jump = 0;
407         unsigned address = 0;
408         //unsigned j;
409         //char buf[EBUFSIZ];
410         
411         SECT * sc = &sect[sno];
412         CHUNK * ch = sc->sffix;
413
414         if (ch == NULL)
415                 return 0;
416
417         // "Cache" first chunk
418         CHUNK * cch = sc->sfcode;
419
420         // Can't fixup a section with nothing in it
421         if (cch == NULL)
422                 return 0;
423
424         do
425         {
426                 fup.cp = ch->chptr;                                     // fup -> start of chunk
427                 fuend = (WORD *)(fup.cp + ch->ch_size); // fuend -> end of chunk
428
429                 while (fup.wp < fuend)
430                 {
431                         w = *fup.wp++;
432                         loc = *fup.lp++;
433                         cfileno = *fup.wp++;
434                         curlineno = (int)*fup.wp++;
435 DEBUG { printf("ResolveFixups: cfileno=%u\n", cfileno); }
436                         // This is based on global vars cfileno, curfname :-P
437                         // This approach is kinda meh as well. I think we can do better than this.
438                         SetFilenameForErrorReporting();
439
440                         esym = NULL;
441
442                         // Search for chunk containing location to fix up; compute a
443                         // pointer to the location (in the chunk). Often we will find the
444                         // fixup is in the "cached" chunk, so the linear-search is seldom
445                         // executed.
446                         if (loc < cch->chloc || loc >= (cch->chloc + cch->ch_size))
447                         {
448                                 for(cch=sc->sfcode; cch!=NULL; cch=cch->chnext)
449                                 {
450                                         if (loc >= cch->chloc && loc < (cch->chloc + cch->ch_size))
451                                                 break;
452                                 }
453
454                                 if (cch == NULL)
455                                 {
456                                         // Fixup (loc) out of range 
457                                         interror(7);
458                                         // NOTREACHED
459                                 }
460                         }
461
462                         locp = cch->chptr + (loc - cch->chloc);
463                         eattr = 0;
464
465                         // Compute expression/symbol value and attribs
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 ((eattr & (GLOBAL | DEFINED)) == GLOBAL)
491                                         esym = sy;
492                         }
493
494                         tdb = (WORD)(eattr & TDB);
495
496                         // If the expression is undefined and no external symbol is
497                         // involved, then it's an error.
498                         if (!(eattr & DEFINED) && (esym == NULL))
499                         {
500                                 error(undef_error);
501                                 continue;
502                         }
503
504 // It seems that this is completely unnecessary!
505 #if 0
506                         if (((w & FUMASKRISC) == FU_MOVEI) && esym)
507 //{
508 //printf("DoFixups: Setting symbol attre to RISCSYM...\n");
509                                 esym->sattre |= RISCSYM;
510 //}
511 #endif
512
513                         // Do the fixup
514                         // 
515                         // If a PC-relative fixup is undefined, its value is *not*
516                         // subtracted from the location (that will happen in the linker
517                         // when the external reference is resolved).
518                         // 
519                         // MWC expects PC-relative things to have the LOC subtracted from
520                         // the value, if the value is external (that is, undefined at this
521                         // point).
522                         // 
523                         // PC-relative fixups must be DEFINED and either in the same
524                         // section (whereupon the subtraction takes place) or ABS (with no
525                         // subtract).
526                         if (w & FU_PCREL)
527                         {
528                                 if (eattr & DEFINED)
529                                 {
530                                         if (tdb == sno)
531                                                 eval -= (VALUE)loc;
532                                         else if (tdb)
533                                         {
534                                                 error("PC-relative expr across sections");
535                                                 continue;
536                                         }
537
538                                         if (sbra_flag && (w & FU_LBRA) && (eval + 0x80 < 0x100))
539                                                 warn("unoptimized short branch");
540                                 }
541                                 else if (obj_format == MWC)
542                                         eval -= (VALUE)loc;
543
544                                 tdb = 0;
545                                 eattr &= ~TDB;
546                         }
547
548                         // Do fixup classes
549                         switch ((int)(w & FUMASK))
550                         {
551                         // FU_BBRA fixes up a one-byte branch offset.
552                         case FU_BBRA:
553                                 if (!(eattr & DEFINED))
554                                 {
555                                         error("external short branch");
556                                         continue;
557                                 }
558
559                                 eval -= 2;
560
561                                 if (eval + 0x80 >= 0x100)
562                                         goto range;
563
564                                 if (eval == 0)
565                                 {
566                                         error("illegal bra.s with zero offset");
567                                         continue;
568                                 }
569
570                                 *++locp = (char)eval;
571                                 break;
572                         // Fixup one-byte value at locp + 1.
573                         case FU_WBYTE:
574                                 locp++;
575                                 // FALLTHROUGH
576                         // Fixup one-byte forward references
577                         case FU_BYTE:
578                                 if (!(eattr & DEFINED))
579                                 {
580                                         error("external byte reference");
581                                         continue;
582                                 }
583
584                                 if (tdb)
585                                 {
586                                         error("non-absolute byte reference");
587                                         continue;
588                                 }
589
590                                 if ((w & FU_PCREL) && eval + 0x80 >= 0x100)
591                                         goto range;
592
593                                 if (w & FU_SEXT)
594                                 {
595                                         if (eval + 0x100 >= 0x200)
596                                                 goto range;
597                                 }
598                                 else if (eval >= 0x100)
599                                         goto range;
600
601                                 *locp = (char)eval;
602                                 break;
603                         // Fixup WORD forward references; 
604                         // the word could be unaligned in the section buffer, so we have to
605                         // be careful.
606                         case FU_WORD:
607                                 if ((w & FUMASKRISC) == FU_JR)// || ((w & 0x0F00) == FU_MJR))
608                                 {
609                                         oaddr = *fup.lp++;
610
611                                         if (oaddr)
612                                                 reg2 = (signed)((eval - (oaddr + 2)) / 2);// & 0x1F;
613                                         else
614                                                 reg2 = (signed)((eval - (loc + 2)) / 2);// & 0x1F;
615
616 #if 0
617                                         if ((w & 0x0F00) == FU_MJR)
618                                         {
619                                                 // Main code destination alignment checking here for
620                                                 // forward declared labels
621                                                 address = (oaddr) ? oaddr : loc;
622
623                                                 if (((address >= 0xF03000) && (address < 0xF04000)
624                                                         && (eval < 0xF03000)) || ((eval >= 0xF03000)
625                                                         && (eval < 0xF04000) && (address < 0xF03000)))
626                                                 {
627                                                         warni("* \'jr\' at $%08X - cannot jump relative between "
628                                                                 "main memory and local gpu ram", address);
629                                                 }
630                                                 else
631                                                 {
632                                                         page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
633
634                                                         if (page_jump)
635                                                         {
636                                                                 // This jump is to a page outside of the
637                                                                 // current 256 byte page
638                                                                 if (eval % 4)
639                                                                 {
640                                                                         warni("* \'jr\' at $%08X - destination address not aligned for long page jump, insert a \'nop\' before the destination address", address);
641                                                                 }
642                                                         }
643                                                         else
644                                                         {
645                                                                 // This jump is in the current 256 byte page
646                                                                 if ((eval - 2) % 4)
647                                                                 {
648                                                                         warni("* \'jr\' at $%08X - destination address not aligned for short page jump, insert a \'nop\' before the destination address", address);
649                                                                 }
650                                                         }
651                                                 }
652                                         }
653 #endif
654
655                                         if ((reg2 < -16) || (reg2 > 15))
656                                         {
657                                                 error("relative jump out of range");
658                                                 break;
659                                         }
660
661                                         *locp = (char)(*locp | ((reg2 >> 3) & 0x03));
662                                         locp++;
663                                         *locp = (char)(*locp | ((reg2 & 0x07) << 5));
664                                         break;
665                                 }
666
667                                 if ((w & FUMASKRISC) == FU_NUM15)
668                                 {
669                                         if (eval < -16 || eval > 15)
670                                         {
671                                                 error("constant out of range");
672                                                 break;
673                                         }
674
675                                         *locp = (char)(*locp | ((eval >> 3) & 0x03));
676                                         locp++;
677                                         *locp = (char)(*locp | ((eval & 0x07) << 5));
678                                         break;
679                                 }
680
681                                 if ((w & FUMASKRISC) == FU_NUM31)
682                                 {
683                                         if (eval < 0 || eval > 31)
684                                         {
685                                                 error("constant out of range");
686                                                 break;
687                                         }
688
689                                         *locp = (char)(*locp | ((eval >> 3) & 0x03));
690                                         locp++;
691                                         *locp = (char)(*locp | ((eval & 0x07) << 5));
692                                         break;
693                                 }
694
695                                 if ((w & FUMASKRISC) == FU_NUM32)
696                                 {
697                                         if (eval < 1 || eval > 32)
698                                         {
699                                                 error("constant out of range");
700                                                 break;
701                                         }
702
703                                         if (w & FU_SUB32)
704                                                 eval = (32 - eval);
705
706                                         eval = (eval == 32) ? 0 : eval;
707                                         *locp = (char)(*locp | ((eval >> 3) & 0x03));
708                                         locp++;
709                                         *locp = (char)(*locp | ((eval & 0x07) << 5));
710                                         break;
711                                 }
712
713                                 if ((w & FUMASKRISC) == FU_REGONE)
714                                 {
715                                         if (eval < 0 || eval > 31)
716                                         {
717                                                 error("register value out of range");
718                                                 break;
719                                         }
720
721                                         *locp = (char)(*locp | ((eval >> 3) & 0x03));
722                                         locp++;
723                                         *locp = (char)(*locp | ((eval & 0x07) << 5));
724                                         break;
725                                 }
726
727                                 if ((w & FUMASKRISC) == FU_REGTWO)
728                                 {
729                                         if (eval < 0 || eval > 31)
730                                         {
731                                                 error("register value out of range");
732                                                 break;
733                                         }
734
735                                         locp++;
736                                         *locp = (char)(*locp | (eval & 0x1F));
737                                         break;
738                                 }
739
740                                 if (!(eattr & DEFINED))
741                                 {
742                                         if (w & FU_PCREL)
743                                                 w = MPCREL | MWORD;
744                                         else
745                                                 w = MWORD;
746
747                                         rmark(sno, loc, 0, w, esym);
748                                 }
749                                 else
750                                 {
751                                         if (tdb)
752                                                 rmark(sno, loc, tdb, MWORD, NULL);
753
754                                         if (w & FU_SEXT)
755                                         {
756                                                 if (eval + 0x10000 >= 0x20000)
757                                                         goto range;
758                                         }
759                                         else
760                                         {
761                                                 // Range-check BRA and DBRA
762                                                 if (w & FU_ISBRA)
763                                                 {
764                                                         if (eval + 0x8000 >= 0x10000)
765                                                         goto range;
766                                                 }
767                                                 else if (eval >= 0x10000)
768                                                         goto range;
769                                         }
770                                 }
771
772                                 *locp++ = (char)(eval >> 8);
773                                 *locp = (char)eval;
774                                 break;
775                         // Fixup LONG forward references;
776                         // the long could be unaligned in the section buffer, so be careful
777                         // (again).
778                         case FU_LONG:
779                                 if ((w & FUMASKRISC) == FU_MOVEI)
780                                 {
781 #if 0
782                                         address = loc + 4;
783
784                                         if (eattr & DEFINED)
785                                         {
786                                                 for(j=0; j<fwindex; j++)
787                                                 {
788                                                         if (fwdjump[j] == address)
789                                                         {
790                                                                 page_jump = (address & 0xFFFFFF00) - (eval & 0xFFFFFF00);
791
792                                                                 if (page_jump)
793                                                                 {
794                                                                         if (eval % 4)
795                                                                         {
796                                                                                 err_setup();
797                                                                                 sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for long page jump, insert a \'nop\' before the destination address", address);
798
799                                                                                 if (listing > 0)
800                                                                                         ship_ln(buf);
801
802                                                                                 if (err_flag)
803                                                                                         write(err_fd, buf, (LONG)strlen(buf));
804                                                                                 else
805                                                                                         printf("%s\n", buf);
806                                                                         }          
807                                                                 }
808                                                                 else
809                                                                 {
810                                                                         if (!(eval & 0x0000000F) || ((eval - 2) % 4))
811                                                                         {
812                                                                                 err_setup();
813                                                                                 sprintf(buf, "* \'jump\' at $%08X - destination address not aligned for short page jump, insert a \'nop\' before the destination address", address);
814
815                                                                                 if (listing > 0)
816                                                                                         ship_ln(buf);
817
818                                                                                 if (err_flag)
819                                                                                         write(err_fd, buf, (LONG)strlen(buf));
820                                                                                 else
821                                                                                         printf("%s\n", buf);
822                                                                         }          
823                                                                 }
824
825                                                                 // Clear this jump as it has been checked
826                                                                 fwdjump[j] = 0;
827                                                                 j = fwindex;
828                                                         }
829                                                 }
830                                         }
831 #endif
832
833                                         // Long constant in MOVEI # is word-swapped, so fix it here
834                                         eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
835                                         flags = (MLONG | MMOVEI);
836                                 }
837                                 else
838                                         flags = MLONG;
839
840                                 if (!(eattr & DEFINED))
841                                 {
842 //printf("Fixup (long): Symbol undefined. loc = $%X, long = $%X, flags = $%x\n", loc, eval, flags);
843                                         rmark(sno, loc, 0, flags, esym);
844                                 }
845                                 else if (tdb)
846                                 {
847 //printf("Fixup (long): TDB = $%X. loc =$%X, long = $%X, flags = $%x\n", tdb, loc, eval, flags);
848                                         rmark(sno, loc, tdb, flags, NULL);
849                                 }
850 //else
851 //printf("Fixup (long): TDB = $%X. loc =$%X, long = $%X, flags = $%x\n", tdb, loc, eval, flags);
852
853                                 *locp++ = (char)(eval >> 24);
854                                 *locp++ = (char)(eval >> 16);
855                                 *locp++ = (char)(eval >> 8);
856                                 *locp = (char)eval;
857                                 break;
858
859                         // Fixup a 3-bit "QUICK" reference in bits 9..1
860                         // (range of 1..8) in a word.  Really bits 1..3 in a byte.
861                         case FU_QUICK:
862                                 if (!(eattr & DEFINED))
863                                 {
864                                         error("External quick reference");
865                                         continue;
866                                 }
867
868                                 if (eval < 1 || eval > 8)
869                                         goto range;
870
871                                 *locp |= (eval & 7) << 1;
872                                 break;
873
874                         // Fix up 6502 funny branch
875                         case FU_6BRA:
876                                 eval -= (loc + 1);
877
878                                 if (eval + 0x80 >= 0x100)
879                                         goto range;
880
881                                 *locp = (char)eval;
882                                 break;
883
884                         default:
885                                 // Bad fixup type--this should *never* happen!
886                                 interror(4);
887                                 // NOTREACHED
888                         }
889                         continue;
890 range:
891                         error("expression out of range");
892                 }
893
894                 ch = ch->chnext;
895         }
896         while (ch != NULL);
897
898         return 0;
899 }
900
901 //
902 // Resolve all fixups
903 //
904 int ResolveAllFixups(void)
905 {
906         //unsigned i;
907         //char buf[EBUFSIZ];
908
909         // Make undefined symbols GLOBL
910         if (glob_flag)
911                 ForceUndefinedSymbolsGlobal();
912
913         DEBUG printf("Resolving TEXT sections...\n");
914         ResolveFixups(TEXT);
915         DEBUG printf("Resolving DATA sections...\n");
916         ResolveFixups(DATA);
917
918         return 0;
919 }
920
921