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