]> Shamusworld >> Repos - rmac/blob - direct.c
More correct calculation of ^^ABSCOUNT. Also updated VS project. Now at version 2...
[rmac] / direct.c
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // DIRECT.C - Directive Handling
4 // Copyright (C) 199x Landon Dyer, 2011-2019 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "direct.h"
10 #include "6502.h"
11 #include "amode.h"
12 #include "dsp56k.h"
13 #include "error.h"
14 #include "expr.h"
15 #include "fltpoint.h"
16 #include "listing.h"
17 #include "mach.h"
18 #include "macro.h"
19 #include "mark.h"
20 #include "procln.h"
21 #include "riscasm.h"
22 #include "sect.h"
23 #include "symbol.h"
24 #include "token.h"
25
26 #define DEF_KW
27 #include "kwtab.h"
28
29
30 TOKEN exprbuf[128];                     // Expression buffer
31 SYM * symbolPtr[1000000];       // Symbol pointers table
32 static long unused;                     // For supressing 'write' warnings
33 char buffer[256];                       // Scratch buffer for messages
34 int largestAlign[3] = { 2, 2, 2 };      // Largest alignment value seen per section
35
36 // Function prototypes
37 int d_unimpl(void);
38 int d_68000(void);
39 int d_68020(void);
40 int d_68030(void);
41 int d_68040(void);
42 int d_68060(void);
43 int d_68881(void);
44 int d_68882(void);
45 int d_56001(void);
46 int d_nofpu(void);
47 int d_bss(void);
48 int d_data(void);
49 int d_text(void);
50 int d_abs(void);
51 int d_comm(void);
52 int d_dc(WORD);
53 int d_ds(WORD);
54 int d_dcb(WORD);
55 int d_globl(void);
56 int d_gpu(void);
57 int d_dsp(void);
58 int d_assert(void);
59 int d_include(void);
60 int d_list(void);
61 int d_nlist(void);
62 int d_error(char *);
63 int d_warn(char *);
64 int d_org(void);
65 int d_init(WORD);
66 int d_cargs(void);
67 int d_undmac(void);
68 int d_regbank0(void);
69 int d_regbank1(void);
70 int d_incbin(void);
71 int d_noclear(void);
72 int d_equrundef(void);
73 int d_ccundef(void);
74 int d_print(void);
75 int d_gpumain(void);
76 int d_jpad(void);
77 int d_nojpad(void);
78 int d_fail(void);
79 int d_cstruct(void);
80 int d_prgflags(void);
81 int d_opt(void);
82 int d_dsp(void);
83 int d_objproc(void);
84 void SetLargestAlignment(int);
85
86 // Directive handler table
87 int (*dirtab[])() = {
88         d_org,                          // 0 org
89         d_even,                         // 1 even
90         d_6502,                         // 2 .6502
91         d_68000,                        // 3 .68000
92         d_bss,                          // 4 bss
93         d_data,                         // 5 data
94         d_text,                         // 6 text
95         d_abs,                          // 7 abs
96         d_comm,                         // 8 comm
97         (void *)d_init,         // 9 init
98         d_cargs,                        // 10 cargs
99         (void *)d_goto,         // 11 goto
100         (void *)d_dc,           // 12 dc
101         (void *)d_ds,           // 13 ds
102         d_undmac,                       // 14 undefmac
103         d_gpu,                          // 15 .gpu
104         d_dsp,                          // 16 .dsp
105         (void *)d_dcb,          // 17 dcb
106         d_unimpl,                       // 18* set
107         d_unimpl,                       // 19* reg
108         d_unimpl,                       // 20 dump
109         d_incbin,                       // 21 .incbin //load
110         d_unimpl,                       // 22 disable
111         d_unimpl,                       // 23 enable
112         d_globl,                        // 24 globl
113         d_regbank0,                     // 25 .regbank0
114         d_regbank1,                     // 26 .regbank1
115         d_unimpl,                       // 27 xdef
116         d_assert,                       // 28 assert
117         d_unimpl,                       // 29* if
118         d_unimpl,                       // 30* endif
119         d_unimpl,                       // 31* endc
120         d_unimpl,                       // 32* iif
121         d_include,                      // 33 include
122         fpop,                           // 34 end
123         d_unimpl,                       // 35* macro
124         ExitMacro,                      // 36* exitm
125         d_unimpl,                       // 37* endm
126         d_list,                         // 38 list
127         d_nlist,                        // 39 nlist
128         d_long,                         // 40* rept
129         d_phrase,                       // 41* endr
130         d_dphrase,                      // 42 struct
131         d_qphrase,                      // 43 ends
132         d_title,                        // 44 title
133         d_subttl,                       // 45 subttl
134         eject,                          // 46 eject
135         d_error,                        // 47 error
136         d_warn,                         // 48 warn
137         d_noclear,                      // 49 .noclear
138         d_equrundef,            // 50 .equrundef/.regundef
139         d_ccundef,                      // 51 .ccundef
140         d_print,                        // 52 .print
141         d_cstruct,                      // 53 .cstruct
142         d_jpad,                         // 54 .jpad (deprecated)
143         d_nojpad,                       // 55 .nojpad (deprecated)
144         d_gpumain,                      // 56 .gpumain (deprecated)
145         d_prgflags,                     // 57 .prgflags
146         d_68020,                        // 58 .68020
147         d_68030,                        // 59 .68030
148         d_68040,                        // 60 .68040
149         d_68060,                        // 61 .68060
150         d_68881,                        // 62 .68881
151         d_68882,                        // 63 .68882
152         d_56001,                        // 64 .56001
153         d_nofpu,                        // 65 nofpu
154         d_opt,                          // 66 .opt
155         d_objproc,                      // 67 .objproc
156 };
157
158
159 //
160 // Set the largest alignment seen in the current section
161 //
162 void SetLargestAlignment(int size)
163 {
164         if ((scattr & TEXT) && (largestAlign[0] < size))
165                 largestAlign[0] = size;
166         else if ((scattr & DATA) && (largestAlign[1] < size))
167                 largestAlign[1] = size;
168         else if ((scattr & BSS) && (largestAlign[2] < size))
169                 largestAlign[2] = size;
170 }
171
172
173 //
174 // .error - Abort compilation, printing an error message
175 //
176 int d_error(char *str)
177 {
178         if (*tok == EOL)
179                 return error("error directive encountered - aborting assembling");
180         else
181         {
182                 switch(*tok)
183                 {
184                 case STRING:
185                         return error(string[tok[1]]);
186                         break;
187                 default:
188                         return error("error directive encountered--aborting assembly");
189                 }
190         }
191 }
192
193
194 //
195 // .warn - Just display a warning on screen
196 //
197 int d_warn(char *str)
198 {
199         if (*tok == EOL)
200                 return warn("WARNING WARNING WARNING");
201         else
202         {
203                 switch(*tok)
204                 {
205                 case STRING:
206                         return warn(string[tok[1]]);
207                         break;
208                 default:
209                         return warn("WARNING WARNING WARNING");
210                 }
211         }
212 }
213
214
215 //
216 // .org - Set origin
217 //
218 int d_org(void)
219 {
220         uint64_t address;
221
222         if (!rgpu && !rdsp && !robjproc && !m6502 && !dsp56001)
223                 return error(".org permitted only in GPU/DSP/OP, 56001 and 6502 sections");
224
225         // M56K can leave the expression off the org for some reason :-/
226         // (It's because the expression is non-standard, and so we have to look at
227         // it in isolation)
228         if (!dsp56001 && (abs_expr(&address) == ERROR))
229         {
230                 error("cannot determine org'd address");
231                 return ERROR;
232         }
233
234         if (rgpu | rdsp | robjproc)
235         {
236                 orgaddr = address;
237                 orgactive = 1;
238         }
239         else if (m6502)
240         {
241                 // 6502.  We also kludge 'lsloc' so the listing generator doesn't try
242                 // to spew out megabytes.
243                 if (address > 0xFFFF)
244                         return error(range_error);
245
246                 if (sloc != currentorg[0])
247                 {
248                         currentorg[1] = sloc;
249                         currentorg += 2;
250                 }
251
252                 currentorg[0] = address;
253                 ch_size = 0;
254                 lsloc = sloc = address;
255                 chptr = scode->chptr + address;
256                 orgaddr = address;
257                 orgactive = 1;
258         }
259         else if (dsp56001)
260         {
261                 // Only mark segments we actually wrote something
262                 if (chptr != dsp_currentorg->start && dsp_written_data_in_current_org)
263                 {
264                         dsp_currentorg->end = chptr;
265                         dsp_currentorg++;
266                 }
267
268                 // Maybe we switched from a non-DSP section (TEXT, DATA, etc) and
269                 // scode isn't initialised yet. Not that it's going to be a valid
270                 // scenario, but if we try it anyhow it's going to lead to a crash. So
271                 // let's fudge a value of 0 and get on with it.
272                 orgaddr = (scode != NULL ? sloc : 0);
273                 SaveSection();
274
275                 if (tok[1] != ':')
276                         return error(syntax_error);
277
278                 int sectionToSwitch = 0;
279
280                 switch (tok[0])
281                 {
282                 case KW_X:
283                         dsp_currentorg->memtype = ORG_X;
284                         sectionToSwitch = M56001X;
285                         break;
286
287                 case KW_Y:
288                         dsp_currentorg->memtype = ORG_Y;
289                         sectionToSwitch = M56001Y;
290                         break;
291
292                 case KW_P:
293                         dsp_currentorg->memtype = ORG_P;
294                         sectionToSwitch = M56001P;
295                         break;
296
297                 case KW_L:
298                         dsp_currentorg->memtype = ORG_L;
299                         sectionToSwitch = M56001L;
300                         break;
301
302                 default:
303                         return error("unknown type in ORG");
304                 }
305
306                 if ((obj_format == LOD) || (obj_format == P56))
307                         SwitchSection(sectionToSwitch);
308
309                 tok += 2;
310                 chcheck(3); // Ensure we got a valid address to write
311                 dsp_currentorg->chunk = scode;  // Mark down which chunk this org starts from (will be needed when outputting)
312
313                 if (*tok == EOL)
314                 {
315                         // Well, the user didn't specify an address at all so we'll have to
316                         // use the last used address of that section (or 0 if there wasn't one)
317                         address = orgaddr;
318                         dsp_currentorg->start = chptr;
319                         dsp_currentorg->orgadr = orgaddr;
320                 }
321                 else
322                 {
323                         if (abs_expr(&address) == ERROR)
324                         {
325                                 error("cannot determine org'd address");
326                                 return ERROR;
327                         }
328
329                         dsp_currentorg->start = chptr;
330                         dsp_currentorg->orgadr = (uint32_t)address;
331                         sect[cursect].orgaddr = (uint32_t)address;
332                 }
333
334                 if (address > DSP_MAX_RAM)
335                 {
336                         return error(range_error);
337                 }
338
339                 dsp_written_data_in_current_org = 0;
340
341                 // Copied from 6502 above: kludge `lsloc' so the listing generator
342                 // doesn't try to spew out megabytes.
343                 lsloc = sloc = (int32_t)address;
344 // N.B.: It seems that by enabling this, even though it works elsewhere, will cause symbols to royally fuck up.  Will have to do some digging to figure out why.
345 //              orgactive = 1;
346         }
347
348         ErrorIfNotAtEOL();
349         return 0;
350 }
351
352
353 //
354 // Print directive
355 //
356 int d_print(void)
357 {
358         char prntstr[LNSIZ];            // String for PRINT directive
359         char format[LNSIZ];                     // Format for PRINT directive
360         int formatting = 0;                     // Formatting on/off
361         int wordlong = 0;                       // WORD = 0, LONG = 1
362         int outtype = 0;                        // 0:hex, 1:decimal, 2:unsigned
363
364         uint64_t eval;                          // Expression value
365         WORD eattr;                                     // Expression attributes
366         SYM * esym;                                     // External symbol involved in expr.
367         TOKEN r_expr[EXPRSIZE];
368
369         while (*tok != EOL)
370         {
371                 switch (*tok)
372                 {
373                 case STRING:
374                         sprintf(prntstr, "%s", string[tok[1]]);
375                         printf("%s", prntstr);
376
377                         if (list_fd)
378                                 unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
379
380                         tok += 2;
381                         break;
382                 case '/':
383                         formatting = 1;
384
385                         // "X" & "L" get tokenized now... :-/ Probably should look into preventing this kind of thing from happening (was added with DSP56K code)
386                         if ((tok[1] != SYMBOL) && (tok[1] != KW_L) && (tok[1] != KW_X))
387                                 goto token_err;
388
389                         if (tok[1] == KW_L)
390                         {
391                                 wordlong = 1;
392                                 tok += 2;
393                         }
394                         else if (tok[1] == KW_X)
395                         {
396                                 outtype = 0;
397                                 tok += 2;
398                         }
399                         else
400                         {
401                                 strcpy(prntstr, string[tok[2]]);
402
403                                 switch (prntstr[0])
404                                 {
405                                 case 'l': case 'L': wordlong = 1; break;
406                                 case 'w': case 'W': wordlong = 0; break;
407                                 case 'x': case 'X': outtype  = 0; break;
408                                 case 'd': case 'D': outtype  = 1; break;
409                                 case 'u': case 'U': outtype  = 2; break;
410                                 default:
411                                         error("unknown print format flag");
412                                         return ERROR;
413                                 }
414
415                                 tok += 3;
416                         }
417
418                         break;
419                 case ',':
420                         tok++;
421                         break;
422                 default:
423                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
424                                 goto token_err;
425                         else
426                         {
427                                 switch(outtype)
428                                 {
429                                 case 0: strcpy(format, "%X"); break;
430                                 case 1: strcpy(format, "%d" ); break;
431                                 case 2: strcpy(format, "%u" ); break;
432                                 }
433
434                                 if (wordlong)
435                                         sprintf(prntstr, format, eval);
436                                 else
437                                         sprintf(prntstr, format, eval & 0xFFFF);
438
439                                 printf("%s", prntstr);
440
441                                 if (list_fd)
442                                         unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
443
444                                 formatting = 0;
445                                 wordlong = 0;
446                                 outtype = 0;
447                         }
448
449                         break;
450                 }
451         }
452
453         printf("\n");
454
455         return 0;
456
457 token_err:
458         error("illegal print token [@ '%s']", prntstr);
459         return ERROR;
460 }
461
462
463 //
464 // Undefine an equated condition code
465 //
466 int d_ccundef(void)
467 {
468         SYM * ccname;
469
470         // Check that we are in a RISC section
471         if (!rgpu && !rdsp)
472         {
473                 error(".ccundef must be defined in .gpu/.dsp section");
474                 return ERROR;
475         }
476
477         if (*tok != SYMBOL)
478         {
479                 error("syntax error; expected symbol");
480                 return ERROR;
481         }
482
483         ccname = lookup(string[tok[1]], LABEL, 0);
484
485         // Make sure symbol is a valid ccdef
486         if (!ccname || !(ccname->sattre & EQUATEDCC))
487         {
488                 error("invalid equated condition name specified");
489                 return ERROR;
490         }
491
492         ccname->sattre |= UNDEF_CC;
493
494         return 0;
495 }
496
497
498 //
499 // Undefine an equated register
500 //
501 int d_equrundef(void)
502 {
503         SYM * regname;
504
505         // Check that we are in a RISC section
506         if (!rgpu && !rdsp)
507                 return error(".equrundef/.regundef must be defined in .gpu/.dsp section");
508
509         while (*tok != EOL)
510         {
511                 // Skip preceeding or seperating commas (if any)
512                 if (*tok == ',')
513                         tok++;
514
515                 // Check we are dealing with a symbol
516                 if (*tok != SYMBOL)
517                         return error("syntax error; expected symbol");
518
519                 // Lookup and undef if equated register
520                 regname = lookup(string[tok[1]], LABEL, 0);
521
522                 if (regname && (regname->sattre & EQUATEDREG))
523                 {
524                         // Reset the attributes of this symbol...
525                         regname->sattr = 0;
526                         regname->sattre &= ~(EQUATEDREG | BANK_0 | BANK_1);
527                         regname->sattre |= UNDEF_EQUR;
528                 }
529
530                 // Skip over symbol token and address
531                 tok += 2;
532         }
533
534         return 0;
535 }
536
537
538 //
539 // Do not allow use of the CLR.L opcode
540 //
541 int d_noclear(void)
542 {
543         warn("CLR.L opcode ignored...");
544         return 0;
545 }
546
547
548 //
549 // Include binary file
550 //
551 int d_incbin(void)
552 {
553         int fd;
554         int bytes = 0;
555         long pos, size, bytesRead;
556         char buf1[256];
557         int i;
558
559         // Check to see if we're in BSS, and, if so, throw an error
560         if (scattr & SBSS)
561         {
562                 error("cannot include binary file \"%s\" in BSS section", string[tok[1]]);
563                 return ERROR;
564         }
565
566         if (*tok != STRING)
567         {
568                 error("syntax error; file to include missing");
569                 return ERROR;
570         }
571
572         // Attempt to open the include file in the current directory, then (if that
573         // failed) try list of include files passed in the enviroment string or by
574         // the "-d" option.
575         if ((fd = open(string[tok[1]], _OPEN_INC)) < 0)
576         {
577                 for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
578                 {
579                         fd = strlen(buf1);
580
581                         // Append path char if necessary
582                         if (fd > 0 && buf1[fd - 1] != SLASHCHAR)
583                                 strcat(buf1, SLASHSTRING);
584
585                         strcat(buf1, string[tok[1]]);
586
587                         if ((fd = open(buf1, _OPEN_INC)) >= 0)
588                                 goto allright;
589                 }
590
591                 return error("cannot open: \"%s\"", string[tok[1]]);
592         }
593
594 allright:
595
596         size = lseek(fd, 0L, SEEK_END);
597         pos = lseek(fd, 0L, SEEK_SET);
598         chcheck(size);
599
600         DEBUG { printf("INCBIN: File '%s' is %li bytes.\n", string[tok[1]], size); }
601
602         char * fileBuffer = (char *)malloc(size);
603         bytesRead = read(fd, fileBuffer, size);
604
605         if (bytesRead != size)
606         {
607                 error("was only able to read %li bytes from binary file (%s, %li bytes)", bytesRead, string[tok[1]], size);
608                 return ERROR;
609         }
610
611         memcpy(chptr, fileBuffer, size);
612         chptr += size;
613         sloc += size;
614         ch_size += size;
615
616         if (orgactive)
617                 orgaddr += size;
618
619         free(fileBuffer);
620         close(fd);
621         return 0;
622 }
623
624
625 //
626 // Set RISC register banks
627 //
628 int d_regbank0(void)
629 {
630         // Set active register bank zero
631         regbank = BANK_0;
632         return 0;
633 }
634
635
636 int d_regbank1(void)
637 {
638         // Set active register bank one
639         regbank = BANK_1;
640         return 0;
641 }
642
643
644 //
645 // Helper function, to cut down on mistakes & typing
646 //
647 static inline void SkipBytes(unsigned bytesToSkip)
648 {
649         if (!bytesToSkip)
650                 return;
651
652         if ((scattr & SBSS) == 0)
653         {
654                 chcheck(bytesToSkip);
655                 D_ZEROFILL(bytesToSkip);
656         }
657         else
658         {
659                 sloc += bytesToSkip;
660
661                 if (orgactive)
662                         orgaddr += bytesToSkip;
663         }
664 }
665
666
667 //
668 // Adjust location to an EVEN value
669 //
670 int d_even(void)
671 {
672         if (m6502)
673                 return error(in_6502mode);
674
675         unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01;
676
677         if (skip)
678         {
679                 if ((scattr & SBSS) == 0)
680                 {
681                         chcheck(1);
682                         D_byte(0);
683                 }
684                 else
685                 {
686                         sloc++;
687
688                         if (orgactive)
689                                 orgaddr++;
690                 }
691         }
692
693         return 0;
694 }
695
696
697 //
698 // Adjust location to a LONG value
699 //
700 int d_long(void)
701 {
702         unsigned lower2Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x03;
703         unsigned bytesToSkip = (0x04 - lower2Bits) & 0x03;
704         SkipBytes(bytesToSkip);
705         SetLargestAlignment(4);
706
707         return 0;
708 }
709
710
711 //
712 // Adjust location to a PHRASE value
713 //
714 // N.B.: We have to handle the GPU/DSP cases separately because you can embed
715 //       RISC code in the middle of a regular 68K section. Also note that all
716 //       of the alignment pseudo-ops will have to be fixed this way.
717 //
718 // This *must* behave differently when in a RISC section, as following sloc
719 // (instead of orgaddr) will fuck things up royally. Note that we do it this
720 // way because you can embed RISC code in a 68K section, and have the origin
721 // pointing to a different alignment in the RISC section than the 68K section.
722 //
723 int d_phrase(void)
724 {
725         unsigned lower3Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x07;
726         unsigned bytesToSkip = (0x08 - lower3Bits) & 0x07;
727         SkipBytes(bytesToSkip);
728         SetLargestAlignment(8);
729
730         return 0;
731 }
732
733
734 //
735 // Adjust location to a DPHRASE value
736 //
737 int d_dphrase(void)
738 {
739         unsigned lower4Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x0F;
740         unsigned bytesToSkip = (0x10 - lower4Bits) & 0x0F;
741         SkipBytes(bytesToSkip);
742         SetLargestAlignment(16);
743
744         return 0;
745 }
746
747
748 //
749 // Adjust location to a QPHRASE value
750 //
751 int d_qphrase(void)
752 {
753         unsigned lower5Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x1F;
754         unsigned bytesToSkip = (0x20 - lower5Bits) & 0x1F;
755         SkipBytes(bytesToSkip);
756         SetLargestAlignment(32);
757
758         return 0;
759 }
760
761
762 //
763 // Do auto-even.  This must be called ONLY if 'sloc' is odd.
764 //
765 // This is made hairy because, if there was a label on the line, we also have
766 // to adjust its value. This won't work with more than one label on the line,
767 // which is OK since multiple labels are only allowed in AS68 kludge mode, and
768 // the C compiler is VERY paranoid and uses ".even" whenever it can
769 //
770 // N.B.: This probably needs the same fixes as above...
771 //
772 void auto_even(void)
773 {
774         if (cursect != M6502)
775         {
776                 if (scattr & SBSS)
777                         sloc++;                         // Bump BSS section
778                 else
779                         D_byte(0);                      // Deposit 0.b in non-BSS
780
781                 if (lab_sym != NULL)    // Bump label if we have to
782                         lab_sym->svalue++;
783         }
784 }
785
786
787 //
788 // Unimplemened directive error
789 //
790 int d_unimpl(void)
791 {
792         return error("unimplemented directive");
793 }
794
795
796 //
797 // Return absolute (not TDB) and defined expression or return an error
798 //
799 int abs_expr(uint64_t * a_eval)
800 {
801         WORD eattr;
802
803         if (expr(exprbuf, a_eval, &eattr, NULL) < 0)
804                 return ERROR;
805
806         if (!(eattr & DEFINED))
807                 return error(undef_error);
808
809         if (eattr & TDB)
810                 return error(rel_error);
811
812         return OK;
813 }
814
815
816 //
817 // Hand symbols in a symbol-list to a function (kind of like mapcar...)
818 //
819 int symlist(int(* func)())
820 {
821         const char * em = "symbol list syntax";
822
823         for(;;)
824         {
825                 if (*tok != SYMBOL)
826                         return error(em);
827
828                 if ((*func)(string[tok[1]]) != OK)
829                         break;
830
831                 tok += 2;
832
833                 if (*tok == EOL)
834                         break;
835
836                 if (*tok != ',')
837                         return error(em);
838
839                 tok++;
840         }
841
842         return 0;
843 }
844
845
846 //
847 // .include "filename"
848 //
849 int d_include(void)
850 {
851         int j;
852         int i;
853         char * fn;
854         char buf[128];
855         char buf1[128];
856
857         if (*tok == STRING)                     // Leave strings ALONE
858                 fn = string[*++tok];
859         else if (*tok == SYMBOL)        // Try to append ".s" to symbols
860         {
861                 strcpy(buf, string[*++tok]);
862                 fext(buf, ".s", 0);
863                 fn = &buf[0];
864         }
865         else                                            // Punt if no STRING or SYMBOL
866                 return error("missing filename");
867
868         // Make sure the user didn't try anything like:
869         // .include equates.s
870         if (*++tok != EOL)
871                 return error("extra stuff after filename--enclose it in quotes");
872
873         // Attempt to open the include file in the current directory, then (if that
874         // failed) try list of include files passed in the enviroment string or by
875         // the "-i" option.
876         if ((j = open(fn, 0)) < 0)
877         {
878                 for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
879                 {
880                         j = strlen(buf1);
881
882                         // Append path char if necessary
883                         if (j > 0 && buf1[j - 1] != SLASHCHAR)
884                                 strcat(buf1, SLASHSTRING);
885
886                         strcat(buf1, fn);
887
888                         if ((j = open(buf1, 0)) >= 0)
889                                 goto allright;
890                 }
891
892                 return error("cannot open: \"%s\"", fn);
893         }
894
895 allright:
896         include(j, fn);
897         return 0;
898 }
899
900
901 //
902 // .assert expression [, expression...]
903 //
904 int d_assert(void)
905 {
906         WORD eattr;
907         uint64_t eval;
908
909         for(; expr(exprbuf, &eval, &eattr, NULL)==OK; ++tok)
910         {
911                 if (!(eattr & DEFINED))
912                         return error("forward or undefined .assert");
913
914                 if (!eval)
915                         return error("assert failure");
916
917                 if (*tok != ',')
918                         break;
919         }
920
921         ErrorIfNotAtEOL();
922         return 0;
923 }
924
925
926 //
927 // .globl symbol [, symbol] <<<cannot make local symbols global>>>
928 //
929 int globl1(char * p)
930 {
931         SYM * sy;
932
933         if (*p == '.')
934                 return error("cannot .globl local symbol");
935
936         if ((sy = lookup(p, LABEL, 0)) == NULL)
937         {
938                 sy = NewSymbol(p, LABEL, 0);
939                 sy->svalue = 0;
940                 sy->sattr = GLOBAL;
941 //printf("glob1: Making global symbol: attr=%04X, eattr=%08X, %s\n", sy->sattr, sy->sattre, sy->sname);
942         }
943         else
944                 sy->sattr |= GLOBAL;
945
946         return OK;
947 }
948
949
950 int d_globl(void)
951 {
952         if (m6502)
953                 return error(in_6502mode);
954
955         symlist(globl1);
956         return 0;
957 }
958
959
960 //
961 // .prgflags expression
962 //
963 int d_prgflags(void)
964 {
965         uint64_t eval;
966
967         if (*tok == EOL)
968                 return error("PRGFLAGS requires value");
969         else if (abs_expr(&eval) == OK)
970         {
971                 PRGFLAGS = (uint32_t)eval;
972                 return 0;
973         }
974         else
975         {
976                 return error("PRGFLAGS requires value");
977         }
978 }
979
980
981 //
982 // .abs [expression]
983 //
984 int d_abs(void)
985 {
986         uint64_t eval;
987
988         if (m6502)
989                 return error(in_6502mode);
990
991         SaveSection();
992
993         if (*tok == EOL)
994                 eval = 0;
995         else if (abs_expr(&eval) != OK)
996                 return 0;
997
998         SwitchSection(ABS);
999         sloc = (uint32_t)eval;
1000         return 0;
1001 }
1002
1003
1004 //
1005 // Switch segments
1006 //
1007 int d_text(void)
1008 {
1009         if (rgpu || rdsp)
1010                 return error("directive forbidden in gpu/dsp mode");
1011         else if (m6502)
1012                 return error(in_6502mode);
1013
1014         if (cursect != TEXT)
1015         {
1016                 SaveSection();
1017                 SwitchSection(TEXT);
1018         }
1019
1020         return 0;
1021 }
1022
1023
1024 int d_data(void)
1025 {
1026         if (rgpu || rdsp)
1027                 return error("directive forbidden in gpu/dsp mode");
1028         else if (m6502)
1029                 return error(in_6502mode);
1030
1031         if (cursect != DATA)
1032         {
1033                 SaveSection();
1034                 SwitchSection(DATA);
1035         }
1036
1037         return 0;
1038 }
1039
1040
1041 int d_bss(void)
1042 {
1043         if (rgpu || rdsp)
1044                 return error("directive forbidden in gpu/dsp mode");
1045         else if (m6502)
1046                 return error(in_6502mode);
1047
1048         if (cursect != BSS)
1049         {
1050                 SaveSection();
1051                 SwitchSection(BSS);
1052         }
1053
1054         return 0;
1055 }
1056
1057
1058 //
1059 // .ds[.size] expression
1060 //
1061 int d_ds(WORD siz)
1062 {
1063         DEBUG { printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc); }
1064
1065         uint64_t eval;
1066
1067         if ((cursect & (M6502 | M56KPXYL)) == 0)
1068         {
1069                 if ((siz != SIZB) && (sloc & 1))        // Automatic .even
1070                         auto_even();
1071         }
1072
1073         if (abs_expr(&eval) != OK)
1074                 return 0;
1075
1076         // Check to see if the value being passed in is negative (who the hell does
1077         // that?--nobody does; it's the code gremlins, or rum, what does it)
1078         // N.B.: Since 'eval' is of type uint32_t, if it goes negative, it will
1079         //       have its high bit set.
1080         if (eval & 0x80000000)
1081                 return error("negative sizes not allowed in DS");
1082
1083         // In non-TDB section (BSS, ABS and M6502) just advance the location
1084         // counter appropriately. In TDB sections, deposit (possibly large) chunks
1085         // of zeroed memory....
1086         if ((scattr & SBSS) || cursect == M6502)
1087         {
1088                 listvalue((uint32_t)eval);
1089                 eval *= siz;
1090                 sloc += (uint32_t)eval;
1091
1092                 if (cursect == M6502)
1093                         chptr += eval;
1094
1095                 just_bss = 1;                                   // No data deposited (8-bit CPU mode)
1096         }
1097         else if (cursect == M56001P || cursect == M56001X || cursect == M56001Y || cursect == M56001L)
1098         {
1099                 // Change segment instead of marking blanks.
1100                 // Only mark segments we actually wrote something
1101                 if (chptr != dsp_currentorg->start && dsp_written_data_in_current_org)
1102                 {
1103                         dsp_currentorg->end = chptr;
1104                         dsp_currentorg++;
1105                         dsp_currentorg->memtype = dsp_currentorg[-1].memtype;
1106                 }
1107
1108                 listvalue((uint32_t)eval);
1109                 sloc += (uint32_t)eval;
1110
1111                 // And now let's create a new segment
1112                 dsp_currentorg->start = chptr;
1113                 dsp_currentorg->chunk = scode;  // Mark down which chunk this org starts from (will be needed when outputting)
1114                 sect[cursect].orgaddr = sloc;
1115                 dsp_currentorg->orgadr = sloc;
1116                 dsp_written_data_in_current_org = 0;
1117
1118                 just_bss = 1;                                   // No data deposited
1119         }
1120         else
1121         {
1122                 dep_block(eval, siz, 0, (DEFINED | ABS), NULL);
1123         }
1124
1125         ErrorIfNotAtEOL();
1126         return 0;
1127 }
1128
1129
1130 //
1131 // dc.b, dc.w / dc, dc.l, dc.i, dc.q, dc.d, dc.s, dc.x
1132 //
1133 int d_dc(WORD siz)
1134 {
1135         WORD eattr;
1136         uint64_t eval;
1137         uint8_t * p;
1138
1139         if ((scattr & SBSS) != 0)
1140                 return error("illegal initialization of section");
1141
1142         // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
1143         if ((cursect != M6502) && (cursect != M56001P) && (cursect != M56001X)
1144                 && (cursect != M56001Y) && (cursect != M56001L)
1145                 && (siz != SIZB) && (sloc & 1))
1146                 auto_even();
1147
1148         // Check to see if we're trying to set LONGS on a non 32-bit aligned
1149         // address in a GPU or DSP section, in their local RAM
1150         if ((siz == SIZL) && (orgaddr & 0x03)
1151                 && ((rgpu && (orgaddr >= 0xF03000) && (orgaddr <= 0xF03FFFF))
1152                 || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF))))
1153                 warn("depositing LONGs on a non-long address in local RAM");
1154
1155         for(;; tok++)
1156         {
1157                 // dc.b 'string' [,] ...
1158                 if (siz == SIZB && (*tok == STRING || *tok == STRINGA8) && (tok[2] == ',' || tok[2] == EOL))
1159                 {
1160                         uint32_t i = strlen(string[tok[1]]);
1161
1162                         if ((challoc - ch_size) < i)
1163                                 chcheck(i);
1164
1165                         if (*tok == STRING)
1166                         {
1167                                 for(p=string[tok[1]]; *p!=EOS; p++)
1168                                         D_byte(*p);
1169                         }
1170                         else if (*tok == STRINGA8)
1171                         {
1172                                 for(p=string[tok[1]]; *p!=EOS; p++)
1173                                         D_byte(strtoa8[*p]);
1174                         }
1175                         else
1176                         {
1177                                 error("String format not supported... yet");
1178                         }
1179
1180                         tok += 2;
1181                         goto comma;
1182                 }
1183
1184                 int movei = 0; // MOVEI flag for dc.i
1185
1186                 if (*tok == DOTI)
1187                 {
1188                         movei = 1;
1189                         tok++;
1190                         siz = SIZL;
1191                 }
1192
1193                 // dc.x <expression>
1194                 SYM * esym = 0;
1195
1196                 if (expr(exprbuf, &eval, &eattr, &esym) != OK)
1197                         return 0;
1198
1199                 uint16_t tdb = eattr & TDB;
1200                 uint16_t defined = eattr & DEFINED;
1201
1202 // N.B.: This is awful.  This needs better handling, rather than just bodging something in that, while works, is basically an ugly wart on the assembler.  !!! FIX !!!
1203                 if (dsp56001)
1204                 {
1205                         if (cursect != M56001L)
1206                         {
1207                                 if (!defined)
1208                                 {
1209                                         AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
1210                                         D_dsp(0);
1211                                 }
1212                                 else
1213                                 {
1214                                         if (eattr & FLOAT)
1215                                         {
1216                                                 double fval = *(double *)&eval;
1217                                                 eval = DoubleToDSPFloat(fval);
1218                                         }
1219                                         else
1220                                         {
1221                                                 if ((uint32_t)eval + 0x1000000 >= 0x2000000)
1222                                                         return error(range_error);
1223                                         }
1224
1225                                         // Deposit DSP word (24-bit)
1226                                         D_dsp(eval);
1227                                 }
1228                         }
1229                         else
1230                         {
1231                                 // In L: we deposit stuff to both X: and Y: instead
1232                                 // We will be a bit lazy and require that there is a 2nd value
1233                                 // in the same source line. (Motorola's assembler can parse
1234                                 // 12-digit hex values, which we can't do at the moment) This
1235                                 // of course requires to parse 2 values in one pass. If there
1236                                 // isn't another value in this line, assume X: value is 0.
1237                                 int secondword = 0;
1238                                 uint32_t evaly;
1239 l_parse_loop:
1240
1241                                 if (!defined)
1242                                 {
1243                                         AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
1244                                         D_dsp(0);
1245                                 }
1246                                 else
1247                                 {
1248                                         if (eattr & FLOAT)
1249                                         {
1250                                                 float fval = *(float *)&eval;
1251                                                 eval = DoubleToDSPFloat(fval);
1252                                         }
1253                                         else
1254                                         {
1255                                                 if (eval + 0x1000000 >= 0x2000000)
1256                                                         return error(range_error);
1257                                         }
1258
1259                                         // Parse 2nd value if we didn't do this yet
1260                                         if (secondword == 0)
1261                                         {
1262                                                 evaly = (uint32_t)eval;
1263                                                 secondword = 1;
1264
1265                                                 if (*tok != ':')
1266                                                 {
1267                                                         // If we don't have a : then we're probably at EOL,
1268                                                         // which means the X: value will be 0
1269                                                         eval = 0;
1270                                                         ErrorIfNotAtEOL();
1271                                                 }
1272                                                 else
1273                                                 {
1274                                                         tok++; // Eat the comma;
1275
1276                                                         if (expr(exprbuf, &eval, &eattr, NULL) != OK)
1277                                                                 return 0;
1278
1279                                                         defined = (WORD)(eattr & DEFINED);
1280                                                         goto l_parse_loop;
1281                                                 }
1282                                         }
1283
1284                                         // Deposit DSP words (24-bit)
1285                                         D_dsp(eval);
1286                                         D_dsp(evaly);
1287                                         sloc--; // We do write 2 DSP words but as far as L: space is concerned we actually advance our counter by one
1288                                 }
1289
1290                         }
1291
1292                         goto comma;
1293                 }
1294
1295                 switch (siz)
1296                 {
1297                 case SIZB:
1298                         if (!defined)
1299                         {
1300                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1301                                 D_byte(0);
1302                         }
1303                         else
1304                         {
1305                                 if (tdb)
1306                                         return error("non-absolute byte value");
1307
1308                                 if (eval + 0x100 >= 0x200)
1309                                         return error("%s (value = $%X)", range_error, eval);
1310
1311                                 D_byte(eval);
1312                         }
1313
1314                         break;
1315
1316                 case SIZW:
1317                 case SIZN:
1318                         if (!defined)
1319                         {
1320                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1321                                 D_word(0);
1322                         }
1323                         else
1324                         {
1325                                 if (eval + 0x10000 >= 0x20000)
1326                                         return error(range_error);
1327
1328                                 if (tdb)
1329                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
1330
1331                                 // Deposit 68000 or 6502 (byte-reversed) word
1332                                 if (cursect != M6502)
1333                                         D_word(eval)
1334                                 else
1335                                         D_rword(eval)
1336                         }
1337
1338                         break;
1339
1340                 case SIZL:
1341                         // Shamus: Why can't we do longs in 6502 mode?
1342                         if (m6502)
1343                                 return error(in_6502mode);
1344
1345                         if (!defined)
1346                         {
1347                                 AddFixup(FU_LONG | (movei ? FU_MOVEI : 0), sloc, exprbuf);
1348                                 D_long(0);
1349                         }
1350                         else
1351                         {
1352                                 if (tdb)
1353                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
1354
1355                                 if (movei)
1356                                         eval = WORDSWAP32(eval);
1357
1358                                 D_long(eval);
1359                         }
1360
1361                         break;
1362
1363                 case SIZQ:
1364                         // 64-bit size
1365                         if (m6502)
1366                                 return error(in_6502mode);
1367
1368                         // DEFINITELY NEED FIXUPS HERE!
1369                         if (!defined)
1370                         {
1371                                 AddFixup(FU_QUAD, sloc, exprbuf);
1372                                 eval = 0;
1373                         }
1374
1375                         D_quad(eval);
1376                         break;
1377
1378                 case SIZS:
1379                         // 32-bit float size
1380                         if (m6502)
1381                                 return error(in_6502mode);
1382
1383 /* Seems to me that if something is undefined here, then that should be an error.  Likewise for the D & X variants. */
1384                         if (!defined)
1385                         {
1386 //                              AddFixup(FU_FLOATSING, sloc, exprbuf);
1387 //                              D_long(0);
1388                                 return error("labels not allowed in floating point expressions");
1389                         }
1390                         else
1391                         {
1392 //Would this *ever* happen?
1393 //                              if (tdb)
1394 //                                      MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
1395
1396                                 PTR ptr;
1397                                 ptr.u64 = &eval;
1398                                 uint32_t ieee754 = FloatToIEEE754((float)*ptr.dp);
1399                                 D_long(ieee754);
1400                         }
1401
1402                         break;
1403
1404                 case SIZD:
1405                         // 64-bit double size
1406                         if (m6502)
1407                                 return error(in_6502mode);
1408
1409                         if (!defined)
1410                         {
1411 //                              AddFixup(FU_FLOATDOUB, sloc, exprbuf);
1412 //                              D_quad(0LL);
1413                                 return error("labels not allowed in floating point expressions");
1414                         }
1415                         else
1416                         {
1417 //Would this *ever* happen?
1418 //                              if (tdb)
1419 //                                      MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
1420
1421                                 PTR ptr;
1422                                 ptr.u64 = &eval;
1423                                 uint64_t ieee754 = DoubleToIEEE754(*ptr.dp);
1424                                 D_quad(ieee754);
1425                         }
1426
1427                         break;
1428
1429                 case SIZX:
1430                         if (m6502)
1431                                 return error(in_6502mode);
1432
1433                         uint8_t extDbl[12];
1434                         memset(extDbl, 0, 12);
1435
1436                         if (!defined)
1437                         {
1438 //                              AddFixup(FU_FLOATEXT, sloc, exprbuf);
1439 //                              D_extend(extDbl);
1440                                 return error("labels not allowed in floating point expressions");
1441                         }
1442                         else
1443                         {
1444 //Would this *ever* happen?
1445 //                              if (tdb)
1446 //                                      MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
1447
1448                                 PTR ptr;
1449                                 ptr.u64 = &eval;
1450                                 DoubleToExtended(*ptr.dp, extDbl);
1451                                 D_extend(extDbl);
1452                         }
1453
1454                         break;
1455                 }
1456
1457 comma:
1458                 if (*tok != ',')
1459                         break;
1460         }
1461
1462         ErrorIfNotAtEOL();
1463         return 0;
1464 }
1465
1466
1467 //
1468 // dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2'
1469 //
1470 int d_dcb(WORD siz)
1471 {
1472         uint64_t evalc, eval;
1473         WORD eattr;
1474
1475         DEBUG { printf("dcb: section is %s%s%s (scattr=$%X)\n", (cursect & TEXT ? "TEXT" : ""), (cursect & DATA ? " DATA" : ""), (cursect & BSS ? "BSS" : ""), scattr); }
1476
1477         if ((scattr & SBSS) != 0)
1478                 return error("illegal initialization of section");
1479
1480         if (abs_expr(&evalc) != OK)
1481                 return 0;
1482
1483         if (*tok++ != ',')
1484                 return error("missing comma");
1485
1486         if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1487                 return 0;
1488
1489         if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
1490                 auto_even();
1491
1492         dep_block((uint32_t)evalc, siz, (uint32_t)eval, eattr, exprbuf);
1493         return 0;
1494 }
1495
1496
1497 //
1498 // Generalized initialization directive
1499 //
1500 // .init[.siz] [#count,] expression [.size] , ...
1501 //
1502 // The size suffix on the ".init" directive becomes the default size of the
1503 // objects to deposit. If an item is preceeded with a sharp (immediate) sign
1504 // and an expression, it specifies a repeat count. The value to be deposited
1505 // may be followed by a size suffix, which overrides the default size.
1506 //
1507 int d_init(WORD def_siz)
1508 {
1509         uint64_t count;
1510         uint64_t eval;
1511         WORD eattr;
1512         WORD siz;
1513
1514         if ((scattr & SBSS) != 0)
1515                 return error(".init not permitted in BSS or ABS");
1516
1517         if (rgpu || rdsp)
1518                 return error("directive forbidden in gpu/dsp mode");
1519
1520         for(;;)
1521         {
1522                 // Get repeat count (defaults to 1)
1523                 if (*tok == '#')
1524                 {
1525                         tok++;
1526
1527                         if (abs_expr(&count) != OK)
1528                                 return 0;
1529
1530                         if (*tok++ != ',')
1531                                 return error(comma_error);
1532                 }
1533                 else
1534                         count = 1;
1535
1536                 // Evaluate expression to deposit
1537                 if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1538                         return 0;
1539
1540                 switch (*tok++)
1541                 {                                 // Determine size of object to deposit
1542                 case DOTB: siz = SIZB; break;
1543                 case DOTW: siz = SIZB; break;
1544                 case DOTL: siz = SIZL; break;
1545                 default:
1546                         siz = def_siz;
1547                         tok--;
1548                         break;
1549                 }
1550
1551                 dep_block((uint32_t)count, siz, (uint32_t)eval, eattr, exprbuf);
1552
1553                 switch (*tok)
1554                 {
1555                 case EOL:
1556                         return 0;
1557                 case ',':
1558                         tok++;
1559                         continue;
1560                 default:
1561                         return error(comma_error);
1562                 }
1563         }
1564 }
1565
1566
1567 //
1568 // Deposit 'count' values of size 'siz' in the current (non-BSS) segment
1569 //
1570 int dep_block(uint32_t count, WORD siz, uint32_t eval, WORD eattr, TOKEN * exprbuf)
1571 {
1572         WORD tdb = eattr & TDB;
1573         WORD defined = eattr & DEFINED;
1574
1575         while (count--)
1576         {
1577                 if ((challoc - ch_size) < 4)
1578                         chcheck(4L);
1579
1580                 switch(siz)
1581                 {
1582                 case SIZB:
1583                         if (!defined)
1584                         {
1585                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1586                                 D_byte(0);
1587                         }
1588                         else
1589                         {
1590                                 if (tdb)
1591                                         return error("non-absolute byte value");
1592
1593                                 if (eval + 0x100 >= 0x200)
1594                                         return error(range_error);
1595
1596                                 D_byte(eval);
1597                         }
1598
1599                         break;
1600                 case SIZW:
1601                 case SIZN:
1602                         if (!defined)
1603                         {
1604                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1605                                 D_word(0);
1606                         }
1607                         else
1608                         {
1609                                 if (tdb)
1610                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
1611
1612                                 if (eval + 0x10000 >= 0x20000)
1613                                         return error(range_error);
1614
1615                                 // Deposit 68000 or 6502 (byte-reversed) word
1616                                 if (cursect != M6502)
1617                                         D_word(eval)
1618                                 else
1619                                         D_rword(eval)
1620
1621                         }
1622
1623                         break;
1624                 case SIZL:
1625                         if (m6502)
1626                                 return error(in_6502mode);
1627
1628                         if (!defined)
1629                         {
1630                                 AddFixup(FU_LONG, sloc, exprbuf);
1631                                 D_long(0);
1632                         }
1633                         else
1634                         {
1635                                 if (tdb)
1636                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
1637
1638                                 D_long(eval);
1639                         }
1640
1641                         break;
1642                 }
1643         }
1644
1645         return 0;
1646 }
1647
1648
1649 //
1650 // .comm symbol, size
1651 //
1652 int d_comm(void)
1653 {
1654         SYM * sym;
1655         char * p;
1656         uint64_t eval;
1657
1658         if (m6502)
1659                 return error(in_6502mode);
1660
1661         if (*tok != SYMBOL)
1662                 return error("missing symbol");
1663
1664         p = string[tok[1]];
1665         tok += 2;
1666
1667         if (*p == '.')                                          // Cannot .comm a local symbol
1668                 return error(locgl_error);
1669
1670         if ((sym = lookup(p, LABEL, 0)) == NULL)
1671                 sym = NewSymbol(p, LABEL, 0);
1672         else
1673         {
1674                 if (sym->sattr & DEFINED)
1675                         return error(".comm symbol already defined");
1676         }
1677
1678         sym->sattr = GLOBAL | COMMON | BSS;
1679
1680         if (*tok++ != ',')
1681                 return error(comma_error);
1682
1683         if (abs_expr(&eval) != OK)                      // Parse size of common region
1684                 return 0;
1685
1686         sym->svalue = eval;                                     // Install common symbol's size
1687         ErrorIfNotAtEOL();
1688         return 0;
1689 }
1690
1691
1692 //
1693 // .list - Turn listing on
1694 //
1695 int d_list(void)
1696 {
1697         if (list_flag)
1698                 listing++;
1699
1700         return 0;
1701 }
1702
1703
1704 //
1705 // .nlist - Turn listing off
1706 //
1707 int d_nlist(void)
1708 {
1709         if (list_flag)
1710                 listing--;
1711
1712         return 0;
1713 }
1714
1715
1716 //
1717 // .68000 - Back to 68000 TEXT segment
1718 //
1719 int d_68000(void)
1720 {
1721         rgpu = rdsp = robjproc = dsp56001 = 0;
1722         // Switching from gpu/dsp sections should reset any ORG'd Address
1723         orgactive = 0;
1724         orgwarning = 0;
1725         SaveSection();
1726         SwitchSection(TEXT);
1727         activecpu = CPU_68000;
1728         return 0;
1729 }
1730
1731
1732 //
1733 // .68020 - Back to 68000 TEXT segment and select 68020
1734 //
1735 int d_68020(void)
1736 {
1737         d_68000();
1738         activecpu = CPU_68020;
1739         return 0;
1740 }
1741
1742
1743 //
1744 // .68030 - Back to 68000 TEXT segment and select 68030
1745 //
1746 int d_68030(void)
1747 {
1748         d_68000();
1749         activecpu = CPU_68030;
1750         return 0;
1751 }
1752
1753
1754 //
1755 // .68040 - Back to 68000 TEXT segment and select 68040
1756 //
1757 int d_68040(void)
1758 {
1759         d_68000();
1760         activecpu = CPU_68040;
1761         activefpu = FPU_68040;
1762         return 0;
1763 }
1764
1765
1766 //
1767 // .68060 - Back to 68000 TEXT segment and select 68060
1768 //
1769 int d_68060(void)
1770 {
1771         d_68000();
1772         activecpu = CPU_68060;
1773         activefpu = FPU_68060;
1774         return 0;
1775 }
1776
1777
1778 //
1779 // .68881 - Back to 680x0 TEXT segment and select 68881 FPU
1780 //
1781 int d_68881(void)
1782 {
1783         //d_68000();
1784         activefpu = FPU_68881;
1785         return 0;
1786 }
1787
1788
1789 //
1790 // .68882 - Back to 680x0 TEXT segment and select 68882 FPU
1791 //
1792 int d_68882(void)
1793 {
1794         //d_68000();
1795         activefpu = FPU_68882;
1796         return 0;
1797 }
1798
1799
1800 //
1801 // nofpu - Deselect FPUs.
1802 //
1803 int d_nofpu(void)
1804 {
1805         activefpu = FPU_NONE;
1806         return 0;
1807 }
1808
1809
1810 //
1811 // .56001 - Switch to DSP56001 assembler
1812 //
1813 int d_56001(void)
1814 {
1815         dsp56001 = 1;
1816         rgpu = rdsp = robjproc = 0;
1817         SaveSection();
1818
1819         if ((obj_format == LOD) || (obj_format == P56))
1820                 SwitchSection(M56001P);
1821
1822         return 0;
1823 }
1824
1825
1826 //
1827 // .gpu - Switch to GPU assembler
1828 //
1829 int d_gpu(void)
1830 {
1831         if ((cursect != TEXT) && (cursect != DATA))
1832         {
1833                 error(".gpu can only be used in the TEXT or DATA segments");
1834                 return ERROR;
1835         }
1836
1837         // If previous section was DSP or 68000 then we need to reset ORG'd Addresses
1838         if (!rgpu)
1839         {
1840                 orgactive = 0;
1841                 orgwarning = 0;
1842         }
1843
1844         rgpu = 1;                       // Set GPU assembly
1845         rdsp = 0;                       // Unset DSP assembly
1846         robjproc = 0;           // Unset OP assembly
1847         dsp56001 = 0;           // Unset 56001 assembly
1848         regbank = BANK_N;       // Set no default register bank
1849         return 0;
1850 }
1851
1852
1853 //
1854 // .dsp - Switch to DSP assembler
1855 //
1856 int d_dsp(void)
1857 {
1858         if ((cursect != TEXT) && (cursect != DATA))
1859         {
1860                 error(".dsp can only be used in the TEXT or DATA segments");
1861                 return ERROR;
1862         }
1863
1864         // If previous section was gpu or 68000 then we need to reset ORG'd Addresses
1865         if (!rdsp)
1866         {
1867                 orgactive = 0;
1868                 orgwarning = 0;
1869         }
1870
1871         rdsp = 1;                       // Set DSP assembly
1872         rgpu = 0;                       // Unset GPU assembly
1873         robjproc = 0;           // Unset OP assembly
1874         dsp56001 = 0;           // Unset 56001 assembly
1875         regbank = BANK_N;       // Set no default register bank
1876         return 0;
1877 }
1878
1879
1880 //
1881 // .cargs [#offset], symbol[.size], ...
1882 //
1883 // Lists of registers may also be mentioned; they just take up space. Good for
1884 // "documentation" purposes:
1885 //
1886 // .cargs a6, .arg1, .arg2, .arg3...
1887 //
1888 // Symbols thus created are ABS and EQUATED.
1889 //
1890 int d_cargs(void)
1891 {
1892         uint64_t eval = 4;      // Default to 4 if no offset specified (to account for
1893                                                 // return address)
1894         WORD rlist;
1895         SYM * symbol;
1896         char * p;
1897         int env;
1898         int i;
1899
1900         if (rgpu || rdsp)
1901                 return error("directive forbidden in gpu/dsp mode");
1902
1903         if (*tok == '#')
1904         {
1905                 tok++;
1906
1907                 if (abs_expr(&eval) != OK)
1908                         return 0;
1909
1910                 // Eat the comma, if it's there
1911                 if (*tok == ',')
1912                         tok++;
1913         }
1914
1915         for(;;)
1916         {
1917                 if (*tok == SYMBOL)
1918                 {
1919                         p = string[tok[1]];
1920
1921                         // Set env to either local (dot prefixed) or global scope
1922                         env = (*p == '.' ? curenv : 0);
1923                         symbol = lookup(p, LABEL, env);
1924
1925                         if (symbol == NULL)
1926                         {
1927                                 symbol = NewSymbol(p, LABEL, env);
1928                                 symbol->sattr = 0;
1929                         }
1930                         else if (symbol->sattr & DEFINED)
1931                                 return error("multiply-defined label '%s'", p);
1932
1933                         // Put symbol in "order of definition" list
1934                         AddToSymbolDeclarationList(symbol);
1935
1936                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1937                         symbol->svalue = eval;
1938                         tok += 2;
1939
1940                         // What this does is eat any dot suffixes attached to a symbol. If
1941                         // it's a .L, it adds 4 to eval; if it's .W or .B, it adds 2. If
1942                         // there is no dot suffix, it assumes a size of 2.
1943                         switch ((int)*tok)
1944                         {
1945                         case DOTL:
1946                                 eval += 2;
1947                         case DOTB:
1948                         case DOTW:
1949                                 tok++;
1950                         }
1951
1952                         eval += 2;
1953                 }
1954                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1955                 {
1956                         if (reglist(&rlist) < 0)
1957                                 return 0;
1958
1959                         for(i=0; i<16; i++, rlist>>=1)
1960                         {
1961                                 if (rlist & 1)
1962                                         eval += 4;
1963                         }
1964                 }
1965                 else
1966                 {
1967                         switch ((int)*tok)
1968                         {
1969                         case KW_USP:
1970                         case KW_SSP:
1971                         case KW_PC:
1972                                 eval += 2;
1973                                 // FALLTHROUGH
1974                         case KW_SR:
1975                         case KW_CCR:
1976                                 eval += 2;
1977                                 tok++;
1978                                 break;
1979                         case EOL:
1980                                 return 0;
1981                         default:
1982                                 return error(".cargs syntax");
1983                         }
1984                 }
1985
1986                 // Eat commas in between each argument, if they exist
1987                 if (*tok == ',')
1988                         tok++;
1989         }
1990 }
1991
1992
1993 //
1994 // .cstruct [#offset], symbol[.size], ...
1995 //
1996 // Lists of registers may also be mentioned; they just take up space. Good for
1997 // "documentation" purposes:
1998 //
1999 // .cstruct a6, .arg1, .arg2, .arg3...
2000 //
2001 // Symbols thus created are ABS and EQUATED. Note that this is for
2002 // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for
2003 // the suggestion.
2004 //
2005 int d_cstruct(void)
2006 {
2007         uint64_t eval = 0;      // Default, if no offset specified, is zero
2008         WORD rlist;
2009         SYM * symbol;
2010         char * symbolName;
2011         int env;
2012         int i;
2013
2014         if (rgpu || rdsp)
2015                 return error("directive forbidden in gpu/dsp mode");
2016
2017         if (*tok == '#')
2018         {
2019                 tok++;
2020
2021                 if (abs_expr(&eval) != OK)
2022                         return 0;
2023
2024                 // Eat the comma, if it's there
2025                 if (*tok == ',')
2026                         tok++;
2027         }
2028
2029         for(;;)
2030         {
2031                 if (*tok == SYMBOL)
2032                 {
2033                         symbolName = string[tok[1]];
2034
2035                         // Set env to either local (dot prefixed) or global scope
2036                         env = (symbolName[0] == '.' ? curenv : 0);
2037                         symbol = lookup(symbolName, LABEL, env);
2038
2039                         // If the symbol wasn't found, then define it. Otherwise, throw an
2040                         // error.
2041                         if (symbol == NULL)
2042                         {
2043                                 symbol = NewSymbol(symbolName, LABEL, env);
2044                                 symbol->sattr = 0;
2045                         }
2046                         else if (symbol->sattr & DEFINED)
2047                                 return error("multiply-defined label '%s'", symbolName);
2048
2049                         // Put symbol in "order of definition" list
2050                         AddToSymbolDeclarationList(symbol);
2051
2052                         tok += 2;
2053
2054                         // Adjust label start address if it's a word or a long, as a byte
2055                         // label might have left us on an odd address.
2056                         switch ((int)*tok)
2057                         {
2058                         case DOTW:
2059                         case DOTL:
2060                                 eval += eval & 0x01;
2061                         }
2062
2063                         symbol->sattr |= (ABS | DEFINED | EQUATED);
2064                         symbol->svalue = eval;
2065
2066                         // Check for dot suffixes and adjust space accordingly (longs and
2067                         // words on an odd boundary get bumped to the next word aligned
2068                         // address). If no suffix, then throw an error.
2069                         switch ((int)*tok)
2070                         {
2071                         case DOTL:
2072                                 eval += 4;
2073                                 break;
2074                         case DOTW:
2075                                 eval += 2;
2076                                 break;
2077                         case DOTB:
2078                                 eval += 1;
2079                                 break;
2080                         default:
2081                                 return error("Symbol missing dot suffix in .cstruct construct");
2082                         }
2083
2084                         tok++;
2085                 }
2086                 else if (*tok >= KW_D0 && *tok <= KW_A7)
2087                 {
2088                         if (reglist(&rlist) < 0)
2089                                 return 0;
2090
2091                         for(i=0; i<16; i++, rlist>>=1)
2092                         {
2093                                 if (rlist & 1)
2094                                         eval += 4;
2095                         }
2096                 }
2097                 else
2098                 {
2099                         switch ((int)*tok)
2100                         {
2101                         case KW_USP:
2102                         case KW_SSP:
2103                         case KW_PC:
2104                                 eval += 2;
2105                                 // FALLTHROUGH
2106                         case KW_SR:
2107                         case KW_CCR:
2108                                 eval += 2;
2109                                 tok++;
2110                                 break;
2111                         case EOL:
2112                                 return 0;
2113                         default:
2114                                 return error(".cstruct syntax");
2115                         }
2116                 }
2117
2118                 // Eat commas in between each argument, if they exist
2119                 if (*tok == ',')
2120                         tok++;
2121         }
2122 }
2123
2124
2125 //
2126 // Define start of OP object list (allows the use of ORG)
2127 //
2128 int d_objproc(void)
2129 {
2130         if ((cursect != TEXT) && (cursect != DATA))
2131         {
2132                 error(".objproc can only be used in the TEXT or DATA segments");
2133                 return ERROR;
2134         }
2135
2136         // If previous section was DSP or 68000 then we need to reset ORG'd
2137         // Addresses
2138         if (!robjproc)
2139         {
2140                 orgactive = 0;
2141                 orgwarning = 0;
2142         }
2143
2144         robjproc = 1;           // Set OP assembly
2145         rgpu = 0;                       // Unset GPU assembly
2146         rdsp = 0;                       // Unset DSP assembly
2147         dsp56001 = 0;           // Unset 56001 assembly
2148         return OK;
2149 }
2150
2151
2152 //
2153 // Undefine a macro - .undefmac macname [, macname...]
2154 //
2155 int undmac1(char * p)
2156 {
2157         SYM * symbol = lookup(p, MACRO, 0);
2158
2159         // If the macro symbol exists, cause it to disappear
2160         if (symbol != NULL)
2161                 symbol->stype = (BYTE)SY_UNDEF;
2162
2163         return OK;
2164 }
2165
2166
2167 int d_undmac(void)
2168 {
2169         symlist(undmac1);
2170         return 0;
2171 }
2172
2173
2174 int d_jpad(void)
2175 {
2176         warn("JPAD directive is deprecated/non-functional");
2177         return OK;
2178 }
2179
2180
2181 int d_nojpad(void)
2182 {
2183         warn("NOJPAD directive is deprecated/non-functional");
2184         return OK;
2185 }
2186
2187
2188 int d_gpumain(void)
2189 {
2190         return error("What the hell? Do you think we adhere to the Goof standard?");
2191 }
2192
2193
2194 //
2195 // .opt - turn a specific (or all) optimisation on or off
2196 //
2197 int d_opt(void)
2198 {
2199         while (*tok != EOL)
2200         {
2201                 if (*tok == STRING)
2202                 {
2203                         tok++;
2204                         char * tmpstr = string[*tok++];
2205
2206                         if (ParseOptimization(tmpstr) != OK)
2207                                 return error("unknown optimization flag '%s'", tmpstr);
2208                 }
2209                 else
2210                         return error(".opt directive needs every switch enclosed inside quotation marks");
2211         }
2212
2213         return OK;
2214 }
2215
2216
2217 //
2218 // .if, Start conditional assembly
2219 //
2220 int d_if(void)
2221 {
2222         WORD eattr;
2223         uint64_t eval;
2224         SYM * esym;
2225         IFENT * rif = f_ifent;
2226
2227         // Alloc an IFENTRY
2228         if (rif == NULL)
2229                 rif = (IFENT *)malloc(sizeof(IFENT));
2230         else
2231                 f_ifent = rif->if_prev;
2232
2233         rif->if_prev = ifent;
2234         ifent = rif;
2235
2236         if (!disabled)
2237         {
2238                 if (expr(exprbuf, &eval, &eattr, &esym) != OK)
2239                         return 0;
2240
2241                 if ((eattr & DEFINED) == 0)
2242                         return error(undef_error);
2243
2244                 disabled = !eval;
2245         }
2246
2247         rif->if_state = (WORD)disabled;
2248         return 0;
2249 }
2250
2251
2252 //
2253 // .else, Do alternate case for .if
2254 //
2255 int d_else(void)
2256 {
2257         IFENT * rif = ifent;
2258
2259         if (rif->if_prev == NULL)
2260                 return error("mismatched .else");
2261
2262         if (disabled)
2263                 disabled = rif->if_prev->if_state;
2264         else
2265                 disabled = 1;
2266
2267         rif->if_state = (WORD)disabled;
2268         return 0;
2269 }
2270
2271
2272 //
2273 // .endif, End of conditional assembly block
2274 // This is also called by fpop() to pop levels of IFENTs in case a macro or
2275 // include file exits early with `exitm' or `end'.
2276 //
2277 int d_endif(void)
2278 {
2279         IFENT * rif = ifent;
2280
2281         if (rif->if_prev == NULL)
2282                 return error("mismatched .endif");
2283
2284         ifent = rif->if_prev;
2285         disabled = rif->if_prev->if_state;
2286         rif->if_prev = f_ifent;
2287         f_ifent = rif;
2288         return 0;
2289 }
2290