1 /*
2     the DASM macro assembler (aka small systems cross assembler)
3 
4     Copyright (c) 1988-2002 by Matthew Dillon.
5     Copyright (c) 1995 by Olaf "Rhialto" Seibert.
6     Copyright (c) 2003-2008 by Andrew Davie.
7     Copyright (c) 2008 by Peter H. Froehlich.
8 
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13 
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License along
20     with this program; if not, write to the Free Software Foundation, Inc.,
21     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23 
24 /*
25  *  OPS.C
26  *
27  *  Handle mnemonics and pseudo ops
28  */
29 
30 #include "asm.h"
31 
32 unsigned char Gen[MAXLINE];
33 unsigned char OrgFill = DEFORGFILL;
34 int	 Glen;
35 
36 extern MNEMONIC    Mne6502[];
37 extern MNEMONIC    Mne6803[];
38 extern MNEMONIC    MneHD6303[];
39 extern MNEMONIC    Mne68705[];
40 extern MNEMONIC    Mne68HC11[];
41 extern MNEMONIC    MneF8[];
42 extern MNEMONIC    Mne68908[];
43 
44 void generate(void);
45 void genfill(long fill, long bytes, int size);
46 void pushif(bool xbool);
47 int gethexdig(int c);
48 
49 /*
50 *  An opcode modifies the SEGMENT flags in the following ways:
51 */
52 
v_processor(char * str,MNEMONIC * dummy)53 void v_processor(char *str, MNEMONIC *dummy)
54 {
55     static bool bCalled = false;
56     unsigned long PreviousProcessor = Processor;
57 
58     Processor = 0;
59 
60     if (strcmp(str,"6502") == 0)
61     {
62         if ( !bCalled )
63             addhashtable(Mne6502);
64 
65         MsbOrder = 0;	    /*	lsb,msb */
66         Processor = 6502;
67     }
68 
69     if (strcmp(str,"6803") == 0)
70     {
71         if ( !bCalled )
72             addhashtable(Mne6803);
73 
74         MsbOrder = 1;	    /*	msb,lsb */
75         Processor = 6803;
76     }
77 
78     if (strcmp(str,"HD6303") == 0 || strcmp(str, "hd6303") == 0)
79     {
80         if ( !bCalled )
81         {
82             addhashtable(Mne6803);
83             addhashtable(MneHD6303);
84         }
85 
86         MsbOrder = 1;	    /*	msb,lsb */
87         Processor = 6303;
88     }
89 
90     if (strcmp(str,"68705") == 0)
91     {
92         if ( !bCalled )
93             addhashtable(Mne68705);
94 
95         MsbOrder = 1;	    /*	msb,lsb */
96         Processor = 68705;
97     }
98 
99     if (strcmp(str,"68HC11") == 0 || strcmp(str, "68hc11") == 0)
100     {
101         if ( !bCalled )
102             addhashtable(Mne68HC11);
103 
104         MsbOrder = 1;	    /*	msb,lsb */
105         Processor = 6811;
106     }
107 
108     if (strcmp(str,"F8") == 0 || strcmp(str, "f8") == 0)
109     {
110 		if ( !bCalled )
111 			addhashtable(MneF8);
112 
113 		MsbOrder = 1;
114         Processor = 0xf8;
115     }
116     if ((strcmp(str,"68908") == 0) || (strcmp(str,"68hc908") == 0)) {
117        if ( !bCalled ) {
118            addhashtable(Mne68908);
119        }
120        MsbOrder = 1;           /*  msb,lsb */
121        Processor = 68908;
122     }
123 
124     bCalled = true;
125 
126     if ( !Processor )
127     {
128         asmerr( ERROR_PROCESSOR_NOT_SUPPORTED, true, str );
129     }
130 
131     if ( PreviousProcessor && Processor != PreviousProcessor )
132     {
133         asmerr( ERROR_ONLY_ONE_PROCESSOR_SUPPORTED, true, str );
134     }
135 
136 }
137 
138 #define badcode(mne,adrmode)  (!(mne->okmask & (1L << adrmode)))
139 
140 extern int pass;
141 extern int nMaxPasses;
142 
v_mnemonic(char * str,MNEMONIC * mne)143 void v_mnemonic(char *str, MNEMONIC *mne)
144 {
145     int addrmode;
146     SYMBOL *sym;
147     unsigned int opcode;
148     short opidx;
149     SYMBOL *symbase;
150     int     opsize;
151     bool	byteRequested;
152     char sBuffer[128];
153 
154     Csegment->flags |= SF_REF;
155     programlabel();
156     symbase = eval(str, 1);
157 
158     if ( bTrace )
159         printf("PC: %04lx  MNEMONIC: %s  addrmode: %d  ", Csegment->org, mne->name, symbase->addrmode);
160 
161     for (sym = symbase; sym; sym = sym->next)
162     {
163         if (sym->flags & SYM_UNKNOWN)
164         {
165             ++Redo;
166             Redo_why |= REASON_MNEMONIC_NOT_RESOLVED;
167         }
168     }
169     sym = symbase;
170 
171     if (mne->flags & MF_IMOD)
172     {
173         if (sym->next)
174         {
175             sym->addrmode = AM_BITMOD;
176             if ((mne->flags & MF_REL) && sym->next)
177                 sym->addrmode = AM_BITBRAMOD;
178         }
179     }
180     addrmode = sym->addrmode;
181     if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100)
182         opsize = 2;
183     else
184         opsize = (sym->value) ? 1 : 0;
185 
186     while (badcode(mne,addrmode) && Cvt[addrmode])
187         addrmode = Cvt[addrmode];
188 
189 
190     if ( bTrace )
191         printf("mnemask: %08lx adrmode: %d  Cvt[am]: %d   Mnext:%d   value: %ld\n", mne->okmask, addrmode, Cvt[addrmode], Mnext,  sym->value);
192 
193     if (badcode(mne,addrmode))
194     {
195         sprintf( sBuffer, "%s %s", mne->name, str );
196         asmerr( ERROR_ILLEGAL_ADDRESSING_MODE, false, sBuffer );
197         FreeSymbolList(symbase);
198         //FIX
199             ++Redo;
200             Redo_why |= REASON_MNEMONIC_NOT_RESOLVED;
201         return;
202     }
203 
204 
205     if (Mnext >= 0 && Mnext < NUMOC)            /*	Force	*/
206     {
207         addrmode = Mnext;
208 
209         //FIX: OPCODE.FORCE needs to be adjusted for x,y,sp indexing...
210         switch(sym->addrmode) {
211         	case AM_INDBYTEX:
212         	case AM_INDBYTEY:
213         		// there is only INDWORD to force indirect addressing mode but not with X or Y
214         		// this must be an error
215                 asmerr( ERROR_ILLEGAL_FORCED_ADDRESSING_MODE, false, mne->name );
216                 FreeSymbolList(symbase);
217 
218                 //FIX: Cause assembly to fail when an invalid mode is used for an opcode...
219                 ++Redo;
220                 Redo_why |= REASON_MNEMONIC_NOT_RESOLVED;
221                 return;
222 
223         	case AM_BYTEADR_SP:
224         		addrmode = AM_BYTEADR_SP;
225                 if ((Mnext == AM_WORDADR) || (Mnext == AM_WORDADR_SP))
226                 	addrmode = AM_WORDADR_SP;
227         		break;
228 
229         	case AM_0Y:
230         		addrmode = AM_0Y;
231 
232             	if ((Mnext == AM_WORDADR) || (Mnext == AM_WORDADRY))
233             		addrmode = AM_WORDADRY;
234 
235             	if ((Mnext == AM_BYTEADR) || (Mnext == AM_BYTEADRY))
236             		addrmode = AM_BYTEADRY;
237         		break;
238 
239         	case AM_0X:
240         		addrmode = AM_0X;
241 
242                 if ((Mnext == AM_WORDADR) || (Mnext == AM_WORDADRX))
243                 	addrmode = AM_WORDADRX;
244 
245                 if ((Mnext == AM_BYTEADR) || (Mnext == AM_BYTEADRX))
246                 	addrmode = AM_BYTEADRX;
247         		break;
248         }
249 
250 
251         if (badcode(mne,addrmode))
252         {
253             asmerr( ERROR_ILLEGAL_FORCED_ADDRESSING_MODE, false, mne->name );
254             FreeSymbolList(symbase);
255 
256                //FIX: Cause assembly to fail when an invalid mode is used for an opcode...
257                ++Redo;
258                Redo_why |= REASON_MNEMONIC_NOT_RESOLVED;
259             return;
260         }
261     }
262 
263     if ( bTrace )
264         printf("final addrmode = %d, opsize:%d Opsize[%d]:%d\n", addrmode, opsize, addrmode, Opsize[addrmode]);
265 
266     byteRequested = false;
267     switch(Mnext) {
268     	case AM_IMM8:
269     	case AM_BYTEADR:
270     	case AM_BYTEADRX:
271     	case AM_BYTEADRY:
272     	case AM_BYTEADR_SP:
273     		byteRequested = true;
274     		if (opsize > 1) {
275     			sprintf( sBuffer, "%s %s, user requested byte mode", mne->name, str );
276     			asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
277     		}
278     		break;
279     }
280 
281     switch(addrmode) {
282     	case AM_IMM16:
283     	case AM_WORDADR:
284     	case AM_WORDADRX:
285     	case AM_WORDADRY:
286     	case AM_INDWORD:
287     	case AM_WORDADR_SP:
288     		if ((sym->value > 0xFFFF) || (sym->value < -0xFFFF)) {	// isn't this our space ?
289     			sprintf( sBuffer, "%s %s", mne->name, str );
290     			asmerr( ERROR_ADDRESS_MUST_BE_LT_10000, false, sBuffer );
291     		}
292     		break;
293 
294     	case AM_IMM8:
295     	case AM_BYTEADR:
296     	case AM_BYTEADRX:
297     	case AM_BYTEADRY:
298     	case AM_BYTEADR_SP:
299     		if (sym->value < -0xFF) {	// isn't this our space ?
300     			sprintf( sBuffer, "negative %s %s", mne->name, str );
301     			asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
302     		}
303     		break;
304     }
305 
306     while (opsize > Opsize[addrmode])
307     {
308         if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode]))
309         {
310             if (sym->flags & SYM_UNKNOWN)
311                 break;
312 
313             //FIX: for negative operands...
314             if ( (addrmode == AM_IMM8) && (sym->value <0) )
315             {
316                 opsize=1;
317                 sym->value=(char)(sym->value & 255);
318                 break;
319             }
320 
321 
322 	    if ((sym->value > 255) && !byteRequested) {
323 	    	// automatically increasing address-mode only if user has not explicitly stated
324 		if (addrmode == AM_BYTEADRX) {
325 		    if (! badcode(mne, AM_WORDADRX)) {
326 			addrmode = AM_WORDADRX;
327 			break;
328 		    }
329 		}
330 		if (addrmode == AM_BYTEADRY) {
331 		    if (! badcode(mne, AM_WORDADRY)) {
332 			addrmode = AM_WORDADRY;
333 			break;
334 		    }
335 		}
336 		if (addrmode == AM_BYTEADR_SP) {
337 		    if (! badcode(mne, AM_WORDADR_SP)) {
338 			addrmode = AM_WORDADR_SP;
339 			break;
340 		    }
341 		}
342 	    }
343 
344             sprintf( sBuffer, "%s %s", mne->name, str );
345             asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
346             break;
347         }
348         addrmode = Cvt[addrmode];
349     }
350     opcode = mne->opcode[addrmode];
351     opidx = 1 + (opcode > 0xFF);
352     if (opidx == 2)
353     {
354         Gen[0] = opcode >> 8;
355         Gen[1] = opcode;
356     }
357     else
358     {
359         Gen[0] = opcode;
360     }
361 
362     switch(addrmode)
363     {
364     case AM_BITMOD:
365         sym = symbase->next;
366         if (!(sym->flags & SYM_UNKNOWN) && sym->value >= 0x100) {
367             sprintf( sBuffer, "unknown %s %ld", mne->name, sym->value);
368             asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
369         }
370         Gen[opidx++] = sym->value;
371 
372         if (!(symbase->flags & SYM_UNKNOWN))
373         {
374             if (symbase->value > 7)
375                 asmerr( ERROR_ILLEGAL_BIT_SPECIFICATION, false, str );
376             else
377                 Gen[0] += symbase->value << 1;
378         }
379         break;
380 
381     case AM_BITBRAMOD:
382 
383         if (!(symbase->flags & SYM_UNKNOWN))
384         {
385             if (symbase->value > 7)
386                 asmerr( ERROR_ILLEGAL_BIT_SPECIFICATION, false, str );
387             else
388                 Gen[0] += symbase->value << 1;
389         }
390 
391         sym = symbase->next;
392 
393         if (!(sym->flags & SYM_UNKNOWN) && sym->value >= 0x100) {
394             sprintf( sBuffer, "%s %ld", mne->name, sym->value);
395             asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
396         }
397         Gen[opidx++] = sym->value;
398         sym = sym->next;
399         break;
400 
401     case AM_REL:
402         break;
403 
404     default:
405         if (Opsize[addrmode] > 0)
406             Gen[opidx++] = sym->value;
407         if (Opsize[addrmode] == 2)
408         {
409             if (MsbOrder)
410             {
411                 Gen[opidx-1] = sym->value >> 8;
412                 Gen[opidx++] = sym->value;
413             }
414             else
415             {
416                 Gen[opidx++] = sym->value >> 8;
417             }
418         }
419         sym = sym->next;
420         break;
421     }
422 
423     if (mne->flags & MF_MASK)
424     {
425         if (sym)
426         {
427             if (!(sym->flags & SYM_UNKNOWN) && sym->value >= 0x100) {
428                 sprintf( sBuffer, "unknown && > 256 %s %ld", mne->name, sym->value);
429                 asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
430             }
431             Gen[opidx] = sym->value;
432             sym = sym->next;
433         }
434         else
435         {
436             asmerr( ERROR_NOT_ENOUGH_ARGS, true, NULL );
437         }
438 
439         ++opidx;
440     }
441 
442     if ((mne->flags & MF_REL) || addrmode == AM_REL)
443     {
444         ++opidx;		/*  to end of instruction   */
445 
446         if (!sym)
447             asmerr( ERROR_NOT_ENOUGH_ARGS, true, NULL );
448         else if (!(sym->flags & SYM_UNKNOWN))
449         {
450             long    pc;
451             unsigned char pcf;
452             long    dest;
453 
454             pc = (Csegment->flags & SF_RORG) ? Csegment->rorg : Csegment->org;
455             pcf= (Csegment->flags & SF_RORG) ? Csegment->rflags : Csegment->flags;
456 
457             if ((pcf & (SF_UNKNOWN|2)) == 0)
458             {
459                 dest = sym->value - pc - opidx;
460 
461                 if (dest >= 128 || dest < -128)
462                 {
463                     //FIX: sometimes zero page addressing will first be assumed to be absolute until
464                     //     another pass. ERROR_BRANCH_OUT_OF_RANGE was made non-fatal, but we keep
465                     //     pushing for Redo so assembly won't actually be succesfull until the branch
466                     //     actually works.
467                         sprintf( sBuffer, "%ld", dest );
468                         asmerr( ERROR_BRANCH_OUT_OF_RANGE, false, sBuffer );
469             		++Redo;
470             		Redo_why |= REASON_BRANCH_OUT_OF_RANGE;
471                         sym->flags=sym->flags | SYM_UNKNOWN;
472                         dest = 0;
473                 }
474             }
475             else
476             {
477                 /* Don't bother - we'll take another pass */
478                 dest = 0;
479             }
480             Gen[opidx-1] = dest & 0xFF;     /*	byte before end of inst.    */
481         }
482     }
483     Glen = opidx;
484     generate();
485     FreeSymbolList(symbase);
486 }
487 
v_trace(char * str,MNEMONIC * dummy)488 void v_trace(char *str, MNEMONIC *dummy)
489 {
490     bTrace = (str[1] == 'n');
491 }
492 
v_list(char * str,MNEMONIC * dummy)493 void v_list(char *str, MNEMONIC *dummy)
494 {
495     programlabel();
496 
497     Glen = 0;		/*  Only so outlist() works */
498 
499     if (strncmp(str, "localoff", 7) == 0 || strncmp(str, "LOCALOFF", 7) == 0)
500         pIncfile->flags |=  INF_NOLIST;
501     else if (strncmp(str, "localon", 7) == 0 || strncmp(str, "LOCALON", 7) == 0)
502         pIncfile->flags &= ~INF_NOLIST;
503     else if (strncmp(str, "off", 2) == 0 || strncmp(str, "OFF", 2) == 0)
504         ListMode = 0;
505     else
506         ListMode = 1;
507 }
508 
509 static char *
getfilename(char * str)510 getfilename(char *str)
511 {
512     if (*str == '\"') {
513         char	*buf;
514 
515         str++;
516         buf = ckmalloc(strlen(str)+1);
517         strcpy(buf, str);
518 
519         for (str = buf; *str && *str != '\"'; ++str);
520         *str = 0;
521 
522         return buf;
523     }
524     return str;
525 }
526 
527 void
v_include(char * str,MNEMONIC * dummy)528 v_include(char *str, MNEMONIC *dummy)
529 {
530   SYMBOL *sym;
531 
532   programlabel();
533 
534   // only eval the string if it's compliant with symbol naming
535   if ((*str<'0')||(*str>'9')) //check could be more comprehensive
536     sym = eval(str, 0);
537   else
538     sym = NULL;
539 
540   if ( (sym) && (sym->flags & SYM_STRING ) )
541   {
542     pushinclude(sym->string);
543   }
544   else
545   {
546     char *buf;
547     buf = getfilename(str);
548 
549     pushinclude(buf);
550 
551     if (buf != str)
552       free(buf);
553   }
554 
555   if (sym)
556     FreeSymbolList(sym);
557 }
558 
559 
560 void
v_incbin(char * str,MNEMONIC * dummy)561 v_incbin(char *str, MNEMONIC *dummy)
562 {
563     char    *buf;
564     FILE    *binfile;
565 
566     programlabel();
567     buf = getfilename(str);
568 
569     binfile = pfopen(buf, "rb");
570     if (binfile) {
571         if (Redo) {
572             /* optimize: don't actually read the file if not needed */
573             fseek(binfile, 0, SEEK_END);
574             Glen = ftell(binfile);
575             generate();     /* does not access Gen[] if Redo is set */
576         }
577         else
578         {
579             for (;;) {
580                 Glen = fread(Gen, 1, sizeof(Gen), binfile);
581                 if (Glen <= 0)
582                     break;
583                 generate();
584             }
585         }
586         fclose(binfile);
587     }
588     else
589     {
590         printf("unable to open %s\n", buf);
591     }
592 
593     if (buf != str)
594         free(buf);
595     Glen = 0;		    /* don't list hexdump */
596 }
597 
598 
599 
600 void
v_seg(char * str,MNEMONIC * dummy)601 v_seg(char *str, MNEMONIC *dummy)
602 {
603     SEGMENT *seg;
604 
605     for (seg = Seglist; seg; seg = seg->next) {
606         if (strcmp(str, seg->name) == 0) {
607             Csegment = seg;
608             programlabel();
609             return;
610         }
611     }
612     Csegment = seg = (SEGMENT *)zmalloc(sizeof(SEGMENT));
613     seg->next = Seglist;
614     seg->name = strcpy(ckmalloc(strlen(str)+1), str);
615     seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
616     Seglist = seg;
617     if (Mnext == AM_BSS)
618         seg->flags |= SF_BSS;
619     programlabel();
620 }
621 
622 void
v_hex(char * str,MNEMONIC * dummy)623 v_hex(char *str, MNEMONIC *dummy)
624 {
625     int i;
626     int result;
627 
628     programlabel();
629     Glen = 0;
630     for (i = 0; str[i]; ++i) {
631         if (str[i] == ' ')
632             continue;
633         result = (gethexdig(str[i]) << 4) + gethexdig(str[i+1]);
634         if (str[++i] == 0)
635             break;
636         Gen[Glen++] = result;
637     }
638     generate();
639 }
640 
641 int
gethexdig(int c)642 gethexdig(int c)
643 {
644     char sBuffer[64];
645 
646     if (c >= '0' && c <= '9')
647         return c - '0';
648 
649     if (c >= 'a' && c <= 'f')
650         return c - 'a' + 10;
651 
652     if (c >= 'A' && c <= 'F')
653         return c - 'A' + 10;
654 
655     sprintf( sBuffer, "Bad Hex Digit %c", c );
656     asmerr( ERROR_SYNTAX_ERROR, false, sBuffer );
657 
658     puts("(Must be a valid hex digit)");
659     if (F_listfile)
660         fputs("(Must be a valid hex digit)\n", FI_listfile);
661 
662     return 0;
663 }
664 
665 void
v_err(char * str,MNEMONIC * dummy)666 v_err(char *str, MNEMONIC *dummy)
667 {
668     programlabel();
669     asmerr( ERROR_ERR_PSEUDO_OP_ENCOUNTERED, true, NULL );
670     exit(1);
671 }
672 
673 void
v_dc(char * str,MNEMONIC * mne)674 v_dc(char *str, MNEMONIC *mne)
675 {
676     SYMBOL *sym;
677     SYMBOL *tmp;
678     long  value;
679     char *macstr = 0;		/* "might be used uninitialised" */
680     char vmode = 0;
681     char sBuffer[128];		/* verbose error messages*/
682 
683     Glen = 0;
684     programlabel();
685 
686 
687     /* for byte, .byte, word, .word, long, .long */
688     if (mne->name[0] != 'd') {
689         static char sTmp[4];
690         strcpy(sTmp, "x.x");
691         sTmp[2] = mne->name[0];
692         findext(sTmp);
693     }
694 
695 	/* F8... */
696 
697     /* db, dw, dd */
698     if ( (mne->name[0] == 'd') && (mne->name[1] != 'c') && (mne->name[1] != 'v')) {
699         static char sTmp[4];
700         strcpy(sTmp, "x.x");
701         if ('d' == mne->name[1]) {
702 			sTmp[2] = 'l';
703 		} else {
704             sTmp[2] = mne->name[1];
705 		}
706         findext(sTmp);
707     }
708 
709 	/* ...F8 */
710 
711 
712 
713     if (mne->name[1] == 'v') {
714         int i;
715         vmode = 1;
716         for (i = 0; str[i] && str[i] != ' '; ++i);
717         tmp = findsymbol(str, i);
718         str += i;
719         if (tmp == NULL) {
720             puts("EQM label not found");
721             return;
722         }
723         if (tmp->flags & SYM_MACRO) {
724             macstr = (void *)tmp->string;
725         }
726         else
727         {
728             puts("must specify EQM label for DV");
729             return;
730         }
731     }
732     sym = eval(str, 0);
733     for (; sym; sym = sym->next) {
734         value = sym->value;
735         if (sym->flags & SYM_UNKNOWN) {
736             ++Redo;
737             Redo_why |= REASON_DC_NOT_RESOVED;
738         }
739         if (sym->flags & SYM_STRING) {
740             unsigned char *ptr = (void *)sym->string;
741             while ((value = *ptr) != 0) {
742                 if (vmode) {
743                     setspecial(value, 0);
744                     tmp = eval(macstr, 0);
745                     value = tmp->value;
746                     if (tmp->flags & SYM_UNKNOWN) {
747                         ++Redo;
748                         Redo_why |= REASON_DV_NOT_RESOLVED_PROBABLY;
749                     }
750                     FreeSymbolList(tmp);
751                 }
752                 switch(Mnext) {
753                 default:
754                 case AM_BYTE:
755                     Gen[Glen++] = value & 0xFF;
756                     break;
757                 case AM_WORD:
758                     if (MsbOrder) {
759                         Gen[Glen++] = (value >> 8) & 0xFF;
760                         Gen[Glen++] = value & 0xFF;
761                     }
762                     else
763                     {
764                         Gen[Glen++] = value & 0xFF;
765                         Gen[Glen++] = (value >> 8) & 0xFF;
766                     }
767                     break;
768                 case AM_OTHER_ENDIAN:
769                     if (MsbOrder == 0) {
770                         Gen[Glen++] = (value >> 8) & 0xFF;
771                         Gen[Glen++] = value & 0xFF;
772                     }
773                     else
774                     {
775                         Gen[Glen++] = value & 0xFF;
776                         Gen[Glen++] = (value >> 8) & 0xFF;
777                     }
778                 	break;
779                 case AM_LONG:
780                     if (MsbOrder) {
781                         Gen[Glen++] = (value >> 24)& 0xFF;
782                         Gen[Glen++] = (value >> 16)& 0xFF;
783                         Gen[Glen++] = (value >> 8) & 0xFF;
784                         Gen[Glen++] = value & 0xFF;
785                     }
786                     else
787                     {
788                         Gen[Glen++] = value & 0xFF;
789                         Gen[Glen++] = (value >> 8) & 0xFF;
790                         Gen[Glen++] = (value >> 16)& 0xFF;
791                         Gen[Glen++] = (value >> 24)& 0xFF;
792                     }
793                     break;
794                 }
795                 ++ptr;
796             }
797         }
798         else
799         {
800             if (vmode) {
801                 setspecial(value, sym->flags);
802                 tmp = eval(macstr, 0);
803                 value = tmp->value;
804                 if (tmp->flags & SYM_UNKNOWN) {
805                     ++Redo;
806                     Redo_why |= REASON_DV_NOT_RESOLVED_COULD;
807                 }
808                 FreeSymbolList(tmp);
809             }
810             switch(Mnext) {
811             default:
812             case AM_BYTE:
813                 //any value outside two's complement +ve and +ve byte representation is invalid...
814                 if ((value < -0xFF)||(value > 0xFF))
815 		{
816                     sprintf( sBuffer, "byte %s %ld", mne->name, value);
817                     asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
818 		}
819                 Gen[Glen++] = value & 0xFF;
820                 break;
821             case AM_WORD:
822 		//any value outside two's complement +ve and +ve word representation is invalid...
823                 if ( (bStrictMode) && ((value < -0xFFFF)||(value > 0xFFFF)) )
824 		{
825                     sprintf( sBuffer, "word %s %ld", mne->name, value);
826                     asmerr( ERROR_ADDRESS_MUST_BE_LT_10000, false, sBuffer );
827 		}
828 
829                 if (MsbOrder) {
830                     Gen[Glen++] = (value >> 8) & 0xFF;
831                     Gen[Glen++] = value & 0xFF;
832                 }
833                 else
834                 {
835                     Gen[Glen++] = value & 0xFF;
836                     Gen[Glen++] = (value >> 8) & 0xFF;
837                 }
838                 break;
839             case AM_OTHER_ENDIAN:
840                 if ( (bStrictMode) && ((value < -0xFFFF)||(value > 0xFFFF)) ) {
841                     sprintf( sBuffer, "swapped %s %ld", mne->name, value);
842                     asmerr( ERROR_ADDRESS_MUST_BE_LT_10000, false, sBuffer );
843                 }
844                 if (MsbOrder == 0) {
845                     Gen[Glen++] = (value >> 8) & 0xFF;
846                     Gen[Glen++] = value & 0xFF;
847                 }
848                 else
849                 {
850                     Gen[Glen++] = value & 0xFF;
851                     Gen[Glen++] = (value >> 8) & 0xFF;
852                 }
853             	break;
854             case AM_LONG:
855                 if (MsbOrder) {
856                     Gen[Glen++] = (value >> 24)& 0xFF;
857                     Gen[Glen++] = (value >> 16)& 0xFF;
858                     Gen[Glen++] = (value >> 8) & 0xFF;
859                     Gen[Glen++] = value & 0xFF;
860                 }
861                 else
862                 {
863                     Gen[Glen++] = value & 0xFF;
864                     Gen[Glen++] = (value >> 8) & 0xFF;
865                     Gen[Glen++] = (value >> 16)& 0xFF;
866                     Gen[Glen++] = (value >> 24)& 0xFF;
867                 }
868                 break;
869             }
870         }
871     }
872     generate();
873     FreeSymbolList(sym);
874 }
875 
876 
877 
878 void
v_ds(char * str,MNEMONIC * dummy)879 v_ds(char *str, MNEMONIC *dummy)
880 {
881     SYMBOL *sym;
882     int mult = 1;
883     long filler = 0;
884 
885     if (Mnext == AM_WORD)
886         mult = 2;
887     if (Mnext == AM_LONG)
888         mult = 4;
889     programlabel();
890     if ((sym = eval(str, 0)) != NULL) {
891         if (sym->next)
892             filler = sym->next->value;
893         if (sym->flags & SYM_UNKNOWN) {
894             ++Redo;
895             Redo_why |= REASON_DS_NOT_RESOLVED;
896         }
897         else
898         {
899             if (sym->next && sym->next->flags & SYM_UNKNOWN) {
900                 ++Redo;
901                 Redo_why |= REASON_DS_NOT_RESOLVED;
902             }
903             genfill(filler, sym->value, mult);
904         }
905         FreeSymbolList(sym);
906     }
907 }
908 
909 void
v_org(char * str,MNEMONIC * dummy)910 v_org(char *str, MNEMONIC *dummy)
911 {
912     SYMBOL *sym;
913 
914     sym = eval(str, 0);
915     Csegment->org = sym->value;
916 
917     if (sym->flags & SYM_UNKNOWN)
918         Csegment->flags |= SYM_UNKNOWN;
919     else
920         Csegment->flags &= ~SYM_UNKNOWN;
921 
922     if (Csegment->initflags & SYM_UNKNOWN)
923     {
924         Csegment->initorg = sym->value;
925         Csegment->initflags = sym->flags;
926     }
927 
928     if (sym->next)
929     {
930         OrgFill = sym->next->value;
931         if (sym->next->flags & SYM_UNKNOWN)
932             asmerr( ERROR_VALUE_UNDEFINED, true, NULL );
933     }
934 
935     programlabel();
936     FreeSymbolList(sym);
937 }
938 
939 void
v_rorg(char * str,MNEMONIC * dummy)940 v_rorg(char *str, MNEMONIC *dummy)
941 {
942     SYMBOL *sym = eval(str, 0);
943 
944     Csegment->flags |= SF_RORG;
945     if (sym->addrmode != AM_IMP) {
946         Csegment->rorg = sym->value;
947         if (sym->flags & SYM_UNKNOWN)
948             Csegment->rflags |= SYM_UNKNOWN;
949         else
950             Csegment->rflags &= ~SYM_UNKNOWN;
951         if (Csegment->initrflags & SYM_UNKNOWN) {
952             Csegment->initrorg = sym->value;
953             Csegment->initrflags = sym->flags;
954         }
955     }
956     programlabel();
957     FreeSymbolList(sym);
958 }
959 
960 void
v_rend(char * str,MNEMONIC * dummy)961 v_rend(char *str, MNEMONIC *dummy)
962 {
963     programlabel();
964     Csegment->flags &= ~SF_RORG;
965 }
966 
967 void
v_align(char * str,MNEMONIC * dummy)968 v_align(char *str, MNEMONIC *dummy)
969 {
970     SYMBOL *sym = eval(str, 0);
971     unsigned char fill = 0;
972     unsigned char rorg = Csegment->flags & SF_RORG;
973 
974     if (rorg)
975         Csegment->rflags |= SF_REF;
976     else
977         Csegment->flags |= SF_REF;
978     if (sym->next) {
979         if (sym->next->flags & SYM_UNKNOWN) {
980             ++Redo;
981             Redo_why |= REASON_ALIGN_NOT_RESOLVED;
982         }
983         else
984         {
985             fill = sym->next->value;
986         }
987     }
988     if (rorg) {
989         if ((Csegment->rflags | sym->flags) & SYM_UNKNOWN) {
990             ++Redo;
991             Redo_why |= REASON_ALIGN_RELOCATABLE_ORIGIN_NOT_KNOWN;
992         }
993         else
994         {
995             long n = sym->value - (Csegment->rorg % sym->value);
996             if (n != sym->value)
997                 genfill(fill, n, 1);
998         }
999     }
1000     else
1001     {
1002         if ((Csegment->flags | sym->flags) & SYM_UNKNOWN) {
1003             ++Redo;
1004             Redo_why |= REASON_ALIGN_NORMAL_ORIGIN_NOT_KNOWN;
1005         }
1006         else
1007         {
1008             long n = sym->value - (Csegment->org % sym->value);
1009             if (n != sym->value)
1010                 genfill(fill, n, 1);
1011         }
1012     }
1013     FreeSymbolList(sym);
1014     programlabel();
1015 }
1016 
1017 void
v_subroutine(char * str,MNEMONIC * dummy)1018 v_subroutine(char *str, MNEMONIC *dummy)
1019 {
1020     ++Lastlocalindex;
1021     Localindex = Lastlocalindex;
1022     programlabel();
1023 }
1024 
1025 void
v_equ(char * str,MNEMONIC * dummy)1026 v_equ(char *str, MNEMONIC *dummy)
1027 {
1028     SYMBOL *sym = eval(str, 0);
1029     SYMBOL *lab;
1030 
1031 
1032     /*
1033     * If we encounter a line of the form
1034     *   . = expr	; or . EQU expr
1035     * treat it as one of
1036     *     org expr
1037     *     rorg expr
1038     * depending on whether we have a relocatable origin now or not.
1039     */
1040     if (strlen(Av[0]) == 1 && (Av[0][0] == '.'
1041         || (Av[0][0] == '*' && (Av[0][0] = '.') && 1)           /*AD: huh?*/
1042         )) {
1043         /* Av[0][0] = '\0'; */
1044         if (Csegment->flags & SF_RORG)
1045         {
1046             v_rorg(str, dummy);
1047         }
1048         else
1049         {
1050             v_org(str, dummy);
1051         }
1052         return;
1053     }
1054 
1055 
1056     lab = findsymbol(Av[0], strlen(Av[0]));
1057     if (!lab)
1058         lab = CreateSymbol( Av[0], strlen(Av[0]) );
1059     if (!(lab->flags & SYM_UNKNOWN))
1060     {
1061         if (sym->flags & SYM_UNKNOWN)
1062         {
1063             ++Redo;
1064             Redo_why |= REASON_EQU_NOT_RESOLVED;
1065         }
1066         else
1067         {
1068             if (lab->value != sym->value)
1069             {
1070                 asmerr( ERROR_EQU_VALUE_MISMATCH, false, NULL );
1071                 printf("INFO: Label '%s' changed from $%04lx to $%04lx\n",
1072                     Av[0], lab->value, sym->value);
1073                 ++Redo;
1074                 Redo_why |= REASON_EQU_VALUE_MISMATCH;
1075             }
1076         }
1077     }
1078 
1079     lab->value = sym->value;
1080     lab->flags = sym->flags & (SYM_UNKNOWN|SYM_STRING);
1081     lab->string = sym->string;
1082     sym->flags &= ~(SYM_STRING|SYM_MACRO);
1083 
1084     /* List the value */
1085     {
1086         unsigned long v = lab->value;
1087 
1088         Glen = 0;
1089         if (v > 0x0000FFFF)
1090         {
1091             Gen[Glen++] = v >> 24;
1092             Gen[Glen++] = v >> 16;
1093         }
1094         Gen[Glen++] = v >>  8;
1095         Gen[Glen++] = v;
1096     }
1097 
1098 
1099     FreeSymbolList(sym);
1100 }
1101 
1102 void
v_eqm(char * str,MNEMONIC * dummy)1103 v_eqm(char *str, MNEMONIC *dummy)
1104 {
1105     SYMBOL *lab;
1106     int len = strlen(Av[0]);
1107 
1108     if ((lab = findsymbol(Av[0], len)) != NULL) {
1109         if (lab->flags & SYM_STRING)
1110             free(lab->string);
1111     }
1112     else
1113     {
1114         lab = CreateSymbol( Av[0], len );
1115     }
1116     lab->value = 0;
1117     lab->flags = SYM_STRING | SYM_SET | SYM_MACRO;
1118     lab->string = strcpy(ckmalloc(strlen(str)+1), str);
1119 }
1120 
1121 void
v_echo(char * str,MNEMONIC * dummy)1122 v_echo(char *str, MNEMONIC *dummy)
1123 {
1124     SYMBOL *sym = eval(str, 0);
1125     SYMBOL *s;
1126     char buf[256];
1127 
1128     for (s = sym; s; s = s->next) {
1129         if (!(s->flags & SYM_UNKNOWN)) {
1130             if (s->flags & (SYM_MACRO|SYM_STRING))
1131                 sprintf(buf,"%s", s->string);
1132             else
1133                 sprintf(buf,"$%lx", s->value);
1134             if (FI_listfile)
1135                 fprintf(FI_listfile, " %s", buf);
1136             //printf(" %s", buf);
1137             addmsg(" "); // -FXQ supress output until final pass
1138             addmsg(buf);
1139         }
1140     }
1141     //puts("");
1142     addmsg("\n");
1143     if (FI_listfile)
1144         putc('\n', FI_listfile);
1145 }
1146 
v_set(char * str,MNEMONIC * dummy)1147 void v_set(char *str, MNEMONIC *dummy)
1148 {
1149 
1150     SYMBOL *sym, *lab;
1151     char dynamicname[257];
1152     int i = 0,j;
1153     int setundefined = 0;
1154 
1155     while (str[i] && str[i] != '"' && str[i] != ' ' && str[i] != ',' )
1156         i++;
1157 
1158     if(str[i] && str[i] == ',') // is this SET is using the "," eval-concat operator?
1159     {
1160         strncpy(dynamicname, str,256);
1161         if(i<256)
1162             dynamicname[i]=0;
1163         dynamicname[256]=0;
1164         j=strlen(dynamicname);
1165 
1166         // eval-concat argument processing loop...
1167         while (str[i] && str[i] != '"' && str[i] != ' ')
1168         {
1169             if( str[i] == 0 || str[i] == ' ' ) // leave if we've processed all arguments
1170             {
1171                 break;
1172             }
1173             if(str[i+1]=='"') // is this a string constant?
1174             {
1175                 i=i+2; // advance to string contents
1176                 while (str[i] && str[i] != '"' && str[i] != ' ' && str[i] != ',')
1177                 {
1178                     dynamicname[j++]=str[i++];
1179                 }
1180                 if (str[i] && str[i]=='"')
1181                 {
1182                     dynamicname[j]=0;
1183                     i++;
1184                     continue;
1185                 }
1186                 else
1187                 {
1188                     asmerr( ERROR_SYNTAX_ERROR, false, str);
1189                     continue;
1190                 }
1191             } // argument was string constant
1192             else // this argument is a symbol to be evaluated
1193             {
1194                 int t;
1195                 char tempbuf[257];
1196                 char tempval[257];
1197                 SYMBOL *symarg;
1198                 strncpy(tempbuf,str+i+1,256);
1199                 tempbuf[256]=0;
1200                 for(t=0;t<strlen(tempbuf);t++)
1201                 {
1202                     if(tempbuf[t] == ',')
1203                         tempbuf[t]=0;
1204                 }
1205                 symarg = eval(tempbuf,0);
1206                 if(symarg)
1207                 {
1208                     if (symarg->flags & SYM_UNKNOWN) // one of the arguments isn't defined yet
1209                         setundefined++; // ensure the set doesn't actually happen
1210                     else
1211                     {
1212                         snprintf(tempval,256,"%d",(unsigned)symarg->value);
1213                         strcpy(dynamicname+j,tempval);
1214                         j=j+strlen(tempval);
1215                     }
1216                 }
1217                 i++;
1218                 while (str[i] && str[i] != ' ' && str[i] != ',')
1219                     i++;
1220             } // argument was symbol
1221 
1222             continue; // process any remaining arguments
1223         }
1224         dynamicname[i++] = 0;
1225         if (setundefined) // not all of the arguments are defined yet, so skip this SET
1226         {
1227             return;
1228         }
1229         sym = eval(dynamicname,0);
1230     }
1231     else // traditional SET behavior
1232         sym = eval(str, 0);
1233 
1234     lab = findsymbol(Av[0], strlen(Av[0]));
1235     if (!lab)
1236         lab = CreateSymbol( Av[0], strlen(Av[0]) );
1237     lab->value = sym->value;
1238     lab->flags = sym->flags & (SYM_UNKNOWN|SYM_STRING);
1239     lab->string = sym->string;
1240     sym->flags &= ~(SYM_STRING|SYM_MACRO);
1241     FreeSymbolList(sym);
1242 }
1243 
v_setstr(char * symstr,MNEMONIC * dummy)1244 void v_setstr(char *symstr, MNEMONIC *dummy)
1245 {
1246     char str[1024];
1247     snprintf(str,1024,"\"%s\"",symstr);
1248     v_set(str,dummy);
1249 }
1250 
1251 void
v_execmac(char * str,MACRO * mac)1252 v_execmac(char *str, MACRO *mac)
1253 {
1254     INCFILE *inc;
1255     STRLIST *base;
1256     STRLIST **psl, *sl;
1257     char *s1;
1258 
1259     programlabel();
1260 
1261     if (Mlevel == MAXMACLEVEL) {
1262         char errMsg[256];
1263         sprintf(errMsg, " macro [%s] recursion > %d", mac->name, MAXMACLEVEL);
1264         asmerr( ERROR_RECURSION_TOO_DEEP, true, errMsg );
1265         return;
1266     }
1267     ++Mlevel;
1268     base = (STRLIST *)ckmalloc(STRLISTSIZE+strlen(str)+1);
1269     base->next = NULL;
1270     strcpy(base->buf, str);
1271     psl = &base->next;
1272     while (*str && *str != '\n') {
1273         s1 = str;
1274         while (*str && *str != '\n' && *str != ',')
1275             ++str;
1276         sl = (STRLIST *)ckmalloc(STRLISTSIZE+1+(str-s1));
1277         sl->next = NULL;
1278         *psl = sl;
1279         psl = &sl->next;
1280         memcpy(sl->buf, s1, (str-s1));
1281         sl->buf[str-s1] = 0;
1282         if (*str == ',')
1283             ++str;
1284         while (*str == ' ')
1285             ++str;
1286     }
1287 
1288     inc = (INCFILE *)zmalloc(sizeof(INCFILE));
1289     inc->next = pIncfile;
1290     inc->name = mac->name;
1291     inc->fi   = pIncfile->fi;	/* garbage */
1292     inc->lineno = 0;
1293     inc->flags = INF_MACRO;
1294     inc->saveidx = Localindex;
1295 
1296     inc->savedolidx = Localdollarindex;
1297 
1298     inc->strlist = mac->strlist;
1299     inc->args	  = base;
1300     pIncfile = inc;
1301 
1302     ++Lastlocalindex;
1303     Localindex = Lastlocalindex;
1304 
1305     ++Lastlocaldollarindex;
1306     Localdollarindex = Lastlocaldollarindex;
1307 
1308 }
1309 
v_end(char * str,MNEMONIC * dummy)1310 void v_end(char *str, MNEMONIC *dummy)
1311 {
1312     /* Only ENDs current file and any macro calls within it */
1313 
1314     while ( pIncfile->flags & INF_MACRO)
1315         v_endm(NULL, NULL);
1316 
1317     fseek( pIncfile->fi, 0, SEEK_END);
1318 }
1319 
1320 void
v_endm(char * str,MNEMONIC * dummy)1321 v_endm(char *str, MNEMONIC *dummy)
1322 {
1323     INCFILE *inc = pIncfile;
1324     STRLIST *args, *an;
1325 
1326     /* programlabel(); contrary to documentation */
1327     if (inc->flags & INF_MACRO) {
1328         --Mlevel;
1329         for (args = inc->args; args; args = an) {
1330             an = args->next;
1331             free(args);
1332         }
1333         Localindex = inc->saveidx;
1334 
1335         Localdollarindex = inc->savedolidx;
1336 
1337         pIncfile = inc->next;
1338         free(inc);
1339         return;
1340     }
1341     puts("not within a macro");
1342 }
1343 
1344 void
v_mexit(char * str,MNEMONIC * dummy)1345 v_mexit(char *str, MNEMONIC *dummy)
1346 {
1347     v_endm(NULL, NULL);
1348 }
1349 
1350 void
v_ifconst(char * str,MNEMONIC * dummy)1351 v_ifconst(char *str, MNEMONIC *dummy)
1352 {
1353     SYMBOL *sym;
1354 
1355     programlabel();
1356     sym = eval(str, 0);
1357     pushif(sym->flags == 0);
1358     FreeSymbolList(sym);
1359 }
1360 
1361 void
v_ifnconst(char * str,MNEMONIC * dummy)1362 v_ifnconst(char *str, MNEMONIC *dummy)
1363 {
1364     SYMBOL *sym;
1365 
1366     programlabel();
1367     sym = eval(str, 0);
1368     pushif(sym->flags != 0);
1369     FreeSymbolList(sym);
1370 }
1371 
1372 void
v_if(char * str,MNEMONIC * dummy)1373 v_if(char *str, MNEMONIC *dummy)
1374 {
1375     SYMBOL *sym;
1376 
1377     if (!Ifstack->xtrue || !Ifstack->acctrue) {
1378         pushif(0);
1379         return;
1380     }
1381     programlabel();
1382     sym = eval(str, 0);
1383     if (sym->flags) {
1384         ++Redo;
1385         Redo_why |= REASON_IF_NOT_RESOLVED;
1386         pushif(0);
1387         Ifstack->acctrue = 0;
1388 
1389         Redo_if |= 1;
1390 
1391     }
1392     else
1393     {
1394         pushif(!!sym->value);
1395     }
1396     FreeSymbolList(sym);
1397 }
1398 
v_else(char * str,MNEMONIC * dummy)1399 void v_else(char *str, MNEMONIC *dummy)
1400 {
1401     if (Ifstack->acctrue && !(Ifstack->flags & IFF_BASE)) {
1402         programlabel();
1403         Ifstack->xtrue = !Ifstack->xtrue;
1404     }
1405 }
1406 
1407 void
v_endif(char * str,MNEMONIC * dummy)1408 v_endif(char *str, MNEMONIC *dummy)
1409 {
1410     IFSTACK *ifs = Ifstack;
1411 
1412     if (!(ifs->flags & IFF_BASE)) {
1413         if (ifs->acctrue)
1414             programlabel();
1415         if (ifs->file != pIncfile) {
1416             puts("too many endif's");
1417         }
1418         else
1419         {
1420             Ifstack = ifs->next;
1421             free(ifs);
1422         }
1423     }
1424 }
1425 
v_repeat(char * str,MNEMONIC * dummy)1426 void v_repeat(char *str, MNEMONIC *dummy)
1427 {
1428     REPLOOP *rp;
1429     SYMBOL *sym;
1430 
1431     if (!Ifstack->xtrue || !Ifstack->acctrue) {
1432         pushif(0);
1433         return;
1434     }
1435     programlabel();
1436     sym = eval(str, 0);
1437     if (sym->value == 0) {
1438         pushif(0);
1439         FreeSymbolList(sym);
1440         return;
1441     }
1442 
1443 #ifdef DAD
1444 
1445     /* Don't allow negative values for REPEAT loops */
1446 
1447     if ( sym->value < 0 )
1448     {
1449         pushif( 0 );
1450         FreeSymbolList( sym );
1451 
1452         asmerr( ERROR_REPEAT_NEGATIVE, false, NULL );
1453         return;
1454     }
1455 
1456 #endif
1457 
1458     rp = (REPLOOP *)zmalloc(sizeof(REPLOOP));
1459     rp->next = Reploop;
1460     rp->file = pIncfile;
1461     if (pIncfile->flags & INF_MACRO)
1462         rp->seek = (long)pIncfile->strlist;
1463     else
1464         rp->seek = ftell(pIncfile->fi);
1465     rp->lineno = pIncfile->lineno;
1466     rp->count = sym->value;
1467     if ((rp->flags = sym->flags) != 0) {
1468         ++Redo;
1469         Redo_why |= REASON_REPEAT_NOT_RESOLVED;
1470     }
1471     Reploop = rp;
1472     FreeSymbolList(sym);
1473     pushif(1);
1474 }
1475 
1476 void
v_repend(char * str,MNEMONIC * dummy)1477 v_repend(char *str, MNEMONIC *dummy)
1478 {
1479     if (!Ifstack->xtrue || !Ifstack->acctrue) {
1480         v_endif(NULL,NULL);
1481         return;
1482     }
1483     if (Reploop && Reploop->file == pIncfile) {
1484         if (Reploop->flags == 0 && --Reploop->count) {
1485             if (pIncfile->flags & INF_MACRO)
1486                 pIncfile->strlist = (STRLIST *)Reploop->seek;
1487             else
1488                 fseek(pIncfile->fi,Reploop->seek,0);
1489             pIncfile->lineno = Reploop->lineno;
1490         }
1491         else
1492         {
1493             rmnode((void **)&Reploop, sizeof(REPLOOP));
1494             v_endif(NULL,NULL);
1495         }
1496         return;
1497     }
1498     puts("no repeat");
1499 }
1500 
1501 
1502 
1503 STRLIST *incdirlist;
1504 
1505 void
v_incdir(char * str,MNEMONIC * dummy)1506 v_incdir(char *str, MNEMONIC *dummy)
1507 {
1508     STRLIST **tail;
1509     char *buf;
1510     int found = 0;
1511 
1512     buf = getfilename(str);
1513 
1514     for (tail = &incdirlist; *tail; tail = &(*tail)->next) {
1515         if (strcmp((*tail)->buf, buf) == 0)
1516             found = 1;
1517     }
1518 
1519     if (!found) {
1520         STRLIST *newdir;
1521 
1522         newdir = (STRLIST *)permalloc(STRLISTSIZE + 1 + strlen(buf));
1523         strcpy(newdir->buf, buf);
1524         *tail = newdir;
1525     }
1526 
1527     if (buf != str)
1528         free(buf);
1529 }
1530 
1531 static void
addpart(char * dest,const char * dir,const char * file)1532 addpart(char *dest, const char *dir, const char *file)
1533 {
1534 #if 0	/* not needed here */
1535     if (strchr(file, ':')) {
1536         strcpy(dest, file);
1537     }
1538     else
1539 #endif
1540     {
1541         int pos;
1542 
1543         strcpy(dest, dir);
1544         pos = strlen(dest);
1545         if (pos > 0 && dest[pos-1] != ':' && dest[pos-1] != '/') {
1546             dest[pos] = '/';
1547             pos++;
1548         }
1549         strcpy(dest + pos, file);
1550     }
1551 }
1552 
1553 FILE *
pfopen(const char * name,const char * mode)1554 pfopen(const char *name, const char *mode)
1555 {
1556     FILE *f;
1557     STRLIST *incdir;
1558     char *buf;
1559 
1560     f = fopen(name, mode);
1561     if (f)
1562         return f;
1563 
1564     /* Don't use the incdirlist for absolute pathnames */
1565     if (strchr(name, ':'))
1566         return NULL;
1567 
1568     buf = zmalloc(512);
1569 
1570     for (incdir = incdirlist; incdir; incdir = incdir->next) {
1571         addpart(buf, incdir->buf, name);
1572 
1573         f = fopen(buf, mode);
1574         if (f)
1575             break;
1576     }
1577 
1578     free(buf);
1579     return f;
1580 }
1581 
1582 
1583 static long Seglen;
1584 static long Seekback;
1585 
1586 void
generate(void)1587 generate(void)
1588 {
1589     long seekpos;
1590     static unsigned long org;
1591     int i;
1592 
1593     if (!Redo)
1594     {
1595         if (!(Csegment->flags & SF_BSS))
1596         {
1597             for (i = Glen - 1; i >= 0; --i)
1598                 CheckSum += Gen[i];
1599 
1600             if (Fisclear)
1601             {
1602                 Fisclear = 0;
1603                 if (Csegment->flags & SF_UNKNOWN)
1604                 {
1605                     ++Redo;
1606                     Redo_why |= REASON_OBSCURE;
1607                     return;
1608                 }
1609 
1610                 org = Csegment->org;
1611 
1612                 if ( F_format < FORMAT_RAW )
1613                 {
1614                     putc((org & 0xFF), FI_temp);
1615                     putc(((org >> 8) & 0xFF), FI_temp);
1616 
1617                     if ( F_format == FORMAT_RAS )
1618                     {
1619                         Seekback = ftell(FI_temp);
1620                         Seglen = 0;
1621                         putc(0, FI_temp);
1622                         putc(0, FI_temp);
1623                     }
1624                 }
1625             }
1626 
1627             switch(F_format)
1628             {
1629 
1630             default:
1631 
1632                 asmerr( ERROR_BAD_FORMAT, true, "Unhandled internal format specifier" );
1633                 break;
1634 
1635             case FORMAT_RAW:
1636             case FORMAT_DEFAULT:
1637 
1638                 if (Csegment->org < org)
1639                 {
1640                     printf("segment: %s %s  vs current org: %04lx\n",
1641                         Csegment->name, sftos(Csegment->org, Csegment->flags), org);
1642                     asmerr( ERROR_ORIGIN_REVERSE_INDEXED, true, NULL );
1643                     exit(1);
1644                 }
1645 
1646                 while (Csegment->org != org)
1647                 {
1648                     putc(OrgFill, FI_temp);
1649                     ++org;
1650                 }
1651 
1652                 fwrite(Gen, Glen, 1, FI_temp);
1653                 break;
1654 
1655             case FORMAT_RAS:
1656 
1657                 if (org != Csegment->org)
1658                 {
1659                     org = Csegment->org;
1660                     seekpos = ftell(FI_temp);
1661                     fseek(FI_temp, Seekback, 0);
1662                     putc((Seglen & 0xFF), FI_temp);
1663                     putc(((Seglen >> 8) & 0xFF), FI_temp);
1664                     fseek(FI_temp, seekpos, 0);
1665                     putc((org & 0xFF), FI_temp);
1666                     putc(((org >> 8) & 0xFF), FI_temp);
1667                     Seekback = ftell(FI_temp);
1668                     Seglen = 0;
1669                     putc(0, FI_temp);
1670                     putc(0, FI_temp);
1671                 }
1672 
1673                 fwrite(Gen, Glen, 1, FI_temp);
1674                 Seglen += Glen;
1675                 break;
1676 
1677             }
1678             org += Glen;
1679         }
1680     }
1681 
1682     Csegment->org += Glen;
1683 
1684     if (Csegment->flags & SF_RORG)
1685         Csegment->rorg += Glen;
1686 
1687     if (Csegment->org > maxFileSize) {
1688     	char errMsg[128];
1689     	sprintf(errMsg, "code segment growing larger (%ld) than max. allowed file size (%ld)\n"
1690     					,Csegment->org, maxFileSize);
1691     	asmerr( ERROR_RECURSION_TOO_DEEP, true, errMsg );
1692     	return;
1693     }
1694 }
1695 
closegenerate(void)1696 void closegenerate(void)
1697 {
1698     if (!Redo)
1699     {
1700         if ( F_format == FORMAT_RAS )
1701         {
1702             fseek(FI_temp, Seekback, 0);
1703             putc((Seglen & 0xFF), FI_temp);
1704             putc(((Seglen >> 8) & 0xFF), FI_temp);
1705             fseek(FI_temp, 0L, 2);
1706         }
1707     }
1708 }
1709 
1710 void
genfill(long fill,long entries,int size)1711 genfill(long fill, long entries, int size)
1712 {
1713     long bytes = entries;  /*	multiplied later    */
1714     int i;
1715     unsigned char c3,c2,c1,c0;
1716 
1717     if (bytes == 0) {
1718     	// nothing to do
1719         return;
1720     }
1721     if (bytes < 0) {
1722     	asmerr( ERROR_ORIGIN_REVERSE_INDEXED, true, NULL );
1723     	return;
1724     }
1725 
1726     c3 = fill >> 24;
1727     c2 = fill >> 16;
1728     c1 = fill >> 8;
1729     c0 = fill;
1730     switch(size)
1731     {
1732     case 1:
1733         memset(Gen, c0, sizeof(Gen));
1734         break;
1735 
1736     case 2:
1737         bytes <<= 1;
1738         for (i = 0; i < sizeof(Gen); i += 2)
1739         {
1740             if (MsbOrder)
1741             {
1742                 Gen[i+0] = c1;
1743                 Gen[i+1] = c0;
1744             }
1745             else
1746             {
1747                 Gen[i+0] = c0;
1748                 Gen[i+1] = c1;
1749             }
1750         }
1751         break;
1752 
1753     case 4:
1754         bytes <<= 2;
1755         for (i = 0; i < sizeof(Gen); i += 4)
1756         {
1757             if (MsbOrder)
1758             {
1759                 Gen[i+0] = c3;
1760                 Gen[i+1] = c2;
1761                 Gen[i+2] = c1;
1762                 Gen[i+3] = c0;
1763             }
1764             else
1765             {
1766                 Gen[i+0] = c0;
1767                 Gen[i+1] = c1;
1768                 Gen[i+2] = c2;
1769                 Gen[i+3] = c3;
1770             }
1771         }
1772         break;
1773     }
1774 
1775     for (Glen = sizeof(Gen); bytes > sizeof(Gen); bytes -= sizeof(Gen))
1776         generate();
1777     Glen = bytes;
1778     generate();
1779 }
1780 
1781 void
pushif(bool xbool)1782 pushif(bool xbool)
1783 {
1784     IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
1785     ifs->next = Ifstack;
1786     ifs->file = pIncfile;
1787     ifs->flags = 0;
1788     ifs->xtrue  = xbool;
1789     ifs->acctrue = Ifstack->acctrue && Ifstack->xtrue;
1790     Ifstack = ifs;
1791 }
1792