]> Shamusworld >> Repos - rmac/blob - direct.c
The deed has been accomplished.
[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, that does it)
1078         // N.B.: Since 'eval' is of type uint32_t, if it goes negative, it will have
1079         //       its high bit set.
1080         if (eval & 0x80000000)
1081                 return error("negative sizes not allowed");
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
1098         {
1099                 dep_block(eval, siz, 0, (WORD)(DEFINED | ABS), NULL);
1100         }
1101
1102         ErrorIfNotAtEOL();
1103         return 0;
1104 }
1105
1106
1107 //
1108 // dc.b, dc.w / dc, dc.l, dc.i, dc.q, dc.d
1109 //
1110 int d_dc(WORD siz)
1111 {
1112         WORD eattr;
1113         uint64_t eval;
1114         uint8_t * p;
1115
1116         if ((scattr & SBSS) != 0)
1117                 return error("illegal initialization of section");
1118
1119         // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
1120         if ((cursect != M6502) && (cursect != M56001P) && (cursect != M56001X)
1121                 && (cursect != M56001Y) && (cursect != M56001L)
1122                 && (siz != SIZB) && (sloc & 1))
1123                 auto_even();
1124
1125         // Check to see if we're trying to set LONGS on a non 32-bit aligned
1126         // address in a GPU or DSP section, in their local RAM
1127         if ((siz == SIZL) && (orgaddr & 0x03)
1128                 && ((rgpu && (orgaddr >= 0xF03000) && (orgaddr <= 0xF03FFFF))
1129                 || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF))))
1130                 warn("depositing LONGs on a non-long address in local RAM");
1131
1132         for(;; tok++)
1133         {
1134                 // dc.b 'string' [,] ...
1135                 if (siz == SIZB && (*tok == STRING || *tok == STRINGA8) && (tok[2] == ',' || tok[2] == EOL))
1136                 {
1137                         uint32_t i = strlen(string[tok[1]]);
1138
1139                         if ((challoc - ch_size) < i)
1140                                 chcheck(i);
1141
1142                         if (*tok == STRING)
1143                         {
1144                                 for(p=string[tok[1]]; *p!=EOS; p++)
1145                                         D_byte(*p);
1146                         }
1147                         else if (*tok == STRINGA8)
1148                         {
1149                                 for(p=string[tok[1]]; *p!=EOS; p++)
1150                                         D_byte(strtoa8[*p]);
1151                         }
1152                         else
1153                         {
1154                                 error("String format not supported... yet");
1155                         }
1156
1157                         tok += 2;
1158                         goto comma;
1159                 }
1160
1161                 int movei = 0; // MOVEI flag for dc.i
1162
1163                 if (*tok == DOTI)
1164                 {
1165                         movei = 1;
1166                         tok++;
1167                         siz = SIZL;
1168                 }
1169
1170                 // dc.x <expression>
1171                 SYM * esym = 0;
1172
1173                 if (expr(exprbuf, &eval, &eattr, &esym) != OK)
1174                         return 0;
1175
1176                 uint16_t tdb = eattr & TDB;
1177                 uint16_t defined = eattr & DEFINED;
1178
1179 // 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 !!!
1180                 if (dsp56001)
1181                 {
1182                         if (cursect != M56001L)
1183                         {
1184                                 if (!defined)
1185                                 {
1186                                         AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
1187                                         D_dsp(0);
1188                                 }
1189                                 else
1190                                 {
1191                                         if (eattr & FLOAT)
1192                                         {
1193                                                 double fval = *(double *)&eval;
1194
1195                                                 if (fval >= 1)
1196                                                 {
1197                                                         warn("value clamped to +1.");
1198                                                         eval = 0x7fffff;
1199                                                 }
1200                                                 else if (fval <= -1)
1201                                                 {
1202                                                         warn("value clamped to -1.");
1203                                                         eval = 0x800000;
1204                                                 }
1205                                                 else
1206                                                 {
1207                                                         // Convert fraction to 24 bits fixed point with sign and rounding
1208                                                         // Yeah, that cast to int32_t has to be there because casting
1209                                                         // a float to unsigned int is "undefined" according to the C
1210                                                         // standard. Which most compilers seem to do the sensible thing
1211                                                         // and just cast the f**king value properly, except gcc 4.x.x
1212                                                         // for arm (tested on raspbian).
1213                                                         // Thanks, C and gcc! Thanks for making me waste a few hours \o/
1214                                                         eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
1215                                                 }
1216                                         }
1217                                         else
1218                                         {
1219                                                 if ((uint32_t)eval + 0x1000000 >= 0x2000000)
1220                                                         return error(range_error);
1221                                         }
1222
1223                                         // Deposit DSP word (24-bit)
1224                                         D_dsp(eval);
1225                                 }
1226                         }
1227                         else
1228                         {
1229                                 // In L: we deposit stuff to both X: and Y: instead
1230                                 // We will be a bit lazy and require that there is a 2nd value in the same source line.
1231                                 // (Motorola's assembler can parse 12-digit hex values, which we can't do at the moment)
1232                                 // This of course requires to parse 2 values in one pass.
1233                                 // If there isn't another value in this line, assume X: value is 0.
1234                                 int secondword = 0;
1235                                 uint32_t evaly;
1236 l_parse_loop:
1237
1238                                 if (!defined)
1239                                 {
1240                                         AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf);
1241                                         D_dsp(0);
1242                                 }
1243                                 else
1244                                 {
1245                                         if (eattr & FLOAT)
1246                                         {
1247                                                 float fval = *(float *)&eval;
1248                                                 if (fval >= 1)
1249                                                 {
1250                                                         warn("value clamped to +1.");
1251                                                         eval = 0x7fffff;
1252                                                 }
1253                                                 else if (fval <= -1)
1254                                                 {
1255                                                         warn("value clamped to -1.");
1256                                                         eval = 0x800000;
1257                                                 }
1258                                                 else
1259                                                 {
1260                                                         // Convert fraction to 24 bits fixed point with sign and rounding
1261                                                         // Yeah, that cast to int32_t has to be there because casting
1262                                                         // a float to unsigned int is "undefined" according to the C
1263                                                         // standard. Which most compilers seem to do the sensible thing
1264                                                         // and just cast the f**king value properly, except gcc 4.x.x
1265                                                         // for arm (tested on raspbian).
1266                                                         // Thanks, C and gcc! Thanks for making me waste a few hours \o/
1267                                                         eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23));
1268                                                 }
1269                                         }
1270                                         else
1271                                         {
1272                                                 if (eval + 0x1000000 >= 0x2000000)
1273                                                         return error(range_error);
1274                                         }
1275
1276                                         // Parse 2nd value if we didn't do this yet
1277                                         if (secondword == 0)
1278                                         {
1279                                                 evaly = (uint32_t)eval;
1280                                                 secondword = 1;
1281
1282                                                 if (*tok != ':')
1283                                                 {
1284                                                         // If we don't have a : then we're probably at EOL,
1285                                                         // which means the X: value will be 0
1286                                                         eval = 0;
1287                                                         ErrorIfNotAtEOL();
1288                                                 }
1289                                                 else
1290                                                 {
1291                                                         tok++; // Eat the comma;
1292
1293                                                         if (expr(exprbuf, &eval, &eattr, NULL) != OK)
1294                                                                 return 0;
1295
1296                                                         defined = (WORD)(eattr & DEFINED);
1297                                                         goto l_parse_loop;
1298                                                 }
1299                                         }
1300
1301                                         // Deposit DSP words (24-bit)
1302                                         D_dsp(eval);
1303                                         D_dsp(evaly);
1304                                         sloc--; // We do write 2 DSP words but as far as L: space is concerned we actually advance our counter by one
1305                                 }
1306
1307                         }
1308                         goto comma;
1309                 }
1310
1311                 switch (siz)
1312                 {
1313                 case SIZB:
1314                         if (!defined)
1315                         {
1316                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1317                                 D_byte(0);
1318                         }
1319                         else
1320                         {
1321                                 if (tdb)
1322                                         return error("non-absolute byte value");
1323
1324                                 if (eval + 0x100 >= 0x200)
1325                                         return error("%s (value = $%X)", range_error, eval);
1326
1327                                 D_byte(eval);
1328                         }
1329
1330                         break;
1331                 case SIZW:
1332                 case SIZN:
1333                         if (!defined)
1334                         {
1335                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1336                                 D_word(0);
1337                         }
1338                         else
1339                         {
1340                                 if (eval + 0x10000 >= 0x20000)
1341                                         return error(range_error);
1342
1343                                 if (tdb)
1344                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
1345
1346                                 // Deposit 68000 or 6502 (byte-reversed) word
1347                                 if (cursect != M6502)
1348                                         D_word(eval)
1349                                 else
1350                                         D_rword(eval)
1351                         }
1352
1353                         break;
1354                 case SIZL:
1355                         // Shamus: Why can't we do longs in 6502 mode?
1356                         if (m6502)
1357                                 return error(in_6502mode);
1358
1359                         if (!defined)
1360                         {
1361                                 if (movei)
1362                                         AddFixup(FU_LONG | FU_MOVEI, sloc, exprbuf);
1363                                 else
1364                                         AddFixup(FU_LONG, sloc, exprbuf);
1365
1366                                 D_long(0);
1367                         }
1368                         else
1369                         {
1370                                 if (tdb)
1371                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
1372
1373                                 if (movei)
1374                                         eval = WORDSWAP32(eval);
1375
1376                                 D_long(eval);
1377                         }
1378
1379                         break;
1380                 case SIZQ:
1381                         // 64-bit size
1382                         if (m6502)
1383                                 return error(in_6502mode);
1384
1385                         // Shamus: We only handle DC.Q type stuff, will have to add fixups
1386                         //         and stuff later (maybe... might not be needed...)
1387                         // DEFINITELY NEED FIXUPS HERE!
1388                         if (!defined)
1389                         {
1390                                 AddFixup(FU_QUAD, sloc, exprbuf);
1391                                 D_quad(0LL);
1392                         }
1393                         else
1394                         {
1395                                 D_quad(eval);
1396                         }
1397
1398                         break;
1399                 case SIZS:
1400                         // 32-bit float size
1401                         if (m6502)
1402                                 return error(in_6502mode);
1403
1404                         if (!defined)
1405                         {
1406                                 AddFixup(FU_FLOATSING, sloc, exprbuf);
1407                                 D_long(0);
1408                         }
1409                         else
1410                         {
1411 //Would this *ever* happen?
1412 //                              if (tdb)
1413 //                                      MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
1414
1415                                 PTR ptr;
1416                                 ptr.u64 = &eval;
1417                                 uint32_t ieee754 = FloatToIEEE754((float)*ptr.dp);
1418                                 D_long(ieee754);
1419                         }
1420
1421                         break;
1422                 case SIZD:
1423                         // 64-bit double size
1424                         if (m6502)
1425                                 return error(in_6502mode);
1426
1427                         if (!defined)
1428                         {
1429                                 AddFixup(FU_FLOATDOUB, sloc, exprbuf);
1430                                 D_quad(0LL);
1431                         }
1432                         else
1433                         {
1434 //Would this *ever* happen?
1435 //                              if (tdb)
1436 //                                      MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
1437
1438                                 PTR ptr;
1439                                 ptr.u64 = &eval;
1440                                 uint64_t ieee754 = DoubleToIEEE754(*ptr.dp);
1441                                 D_quad(ieee754);
1442                         }
1443
1444                         break;
1445                 case SIZX:
1446                         if (m6502)
1447                                 return error(in_6502mode);
1448
1449                         uint8_t extDbl[12];
1450                         memset(extDbl, 0, 12);
1451
1452                         if (!defined)
1453                         {
1454                                 AddFixup(FU_FLOATEXT, sloc, exprbuf);
1455                                 D_extend(extDbl);
1456                         }
1457                         else
1458                         {
1459 //Would this *ever* happen?
1460 //                              if (tdb)
1461 //                                      MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
1462
1463                                 PTR ptr;
1464                                 ptr.u64 = &eval;
1465                                 DoubleToExtended(*ptr.dp, extDbl);
1466                                 D_extend(extDbl);
1467                         }
1468
1469                         break;
1470                 }
1471
1472 comma:
1473                 if (*tok != ',')
1474                         break;
1475         }
1476
1477         ErrorIfNotAtEOL();
1478         return 0;
1479 }
1480
1481
1482 //
1483 // dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2'
1484 //
1485 int d_dcb(WORD siz)
1486 {
1487         uint64_t evalc, eval;
1488         WORD eattr;
1489
1490         DEBUG { printf("dcb: section is %s%s%s (scattr=$%X)\n", (cursect & TEXT ? "TEXT" : ""), (cursect & DATA ? " DATA" : ""), (cursect & BSS ? "BSS" : ""), scattr); }
1491
1492         if ((scattr & SBSS) != 0)
1493                 return error("illegal initialization of section");
1494
1495         if (abs_expr(&evalc) != OK)
1496                 return 0;
1497
1498         if (*tok++ != ',')
1499                 return error("missing comma");
1500
1501         if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1502                 return 0;
1503
1504         if (cursect != M6502 && (siz != SIZB) && (sloc & 1))
1505                 auto_even();
1506
1507         dep_block((uint32_t)evalc, siz, (uint32_t)eval, eattr, exprbuf);
1508         return 0;
1509 }
1510
1511
1512 //
1513 // Generalized initialization directive
1514 //
1515 // .init[.siz] [#count,] expression [.size] , ...
1516 //
1517 // The size suffix on the ".init" directive becomes the default size of the
1518 // objects to deposit. If an item is preceeded with a sharp (immediate) sign
1519 // and an expression, it specifies a repeat count. The value to be deposited
1520 // may be followed by a size suffix, which overrides the default size.
1521 //
1522 int d_init(WORD def_siz)
1523 {
1524         uint64_t count;
1525         uint64_t eval;
1526         WORD eattr;
1527         WORD siz;
1528
1529         if ((scattr & SBSS) != 0)
1530                 return error(".init not permitted in BSS or ABS");
1531
1532         if (rgpu || rdsp)
1533                 return error("directive forbidden in gpu/dsp mode");
1534
1535         for(;;)
1536         {
1537                 // Get repeat count (defaults to 1)
1538                 if (*tok == '#')
1539                 {
1540                         tok++;
1541
1542                         if (abs_expr(&count) != OK)
1543                                 return 0;
1544
1545                         if (*tok++ != ',')
1546                                 return error(comma_error);
1547                 }
1548                 else
1549                         count = 1;
1550
1551                 // Evaluate expression to deposit
1552                 if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1553                         return 0;
1554
1555                 switch (*tok++)
1556                 {                                 // Determine size of object to deposit
1557                 case DOTB: siz = SIZB; break;
1558                 case DOTW: siz = SIZB; break;
1559                 case DOTL: siz = SIZL; break;
1560                 default:
1561                         siz = def_siz;
1562                         tok--;
1563                         break;
1564                 }
1565
1566                 dep_block((uint32_t)count, siz, (uint32_t)eval, eattr, exprbuf);
1567
1568                 switch (*tok)
1569                 {
1570                 case EOL:
1571                         return 0;
1572                 case ',':
1573                         tok++;
1574                         continue;
1575                 default:
1576                         return error(comma_error);
1577                 }
1578         }
1579 }
1580
1581
1582 //
1583 // Deposit 'count' values of size 'siz' in the current (non-BSS) segment
1584 //
1585 int dep_block(uint32_t count, WORD siz, uint32_t eval, WORD eattr, TOKEN * exprbuf)
1586 {
1587         WORD tdb;
1588         WORD defined;
1589
1590         tdb = (WORD)(eattr & TDB);
1591         defined = (WORD)(eattr & DEFINED);
1592
1593         while (count--)
1594         {
1595                 if ((challoc - ch_size) < 4)
1596                         chcheck(4L);
1597
1598                 switch(siz)
1599                 {
1600                 case SIZB:
1601                         if (!defined)
1602                         {
1603                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1604                                 D_byte(0);
1605                         }
1606                         else
1607                         {
1608                                 if (tdb)
1609                                         return error("non-absolute byte value");
1610
1611                                 if (eval + 0x100 >= 0x200)
1612                                         return error(range_error);
1613
1614                                 D_byte(eval);
1615                         }
1616
1617                         break;
1618                 case SIZW:
1619                 case SIZN:
1620                         if (!defined)
1621                         {
1622                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1623                                 D_word(0);
1624                         }
1625                         else
1626                         {
1627                                 if (tdb)
1628                                         MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
1629
1630                                 if (eval + 0x10000 >= 0x20000)
1631                                         return error(range_error);
1632
1633                                 // Deposit 68000 or 6502 (byte-reversed) word
1634                                 if (cursect != M6502)
1635                                         D_word(eval)
1636                                 else
1637                                         D_rword(eval)
1638
1639                         }
1640
1641                         break;
1642                 case SIZL:
1643                         if (m6502)
1644                                 return error(in_6502mode);
1645
1646                         if (!defined)
1647                         {
1648                                 AddFixup(FU_LONG, sloc, exprbuf);
1649                                 D_long(0);
1650                         }
1651                         else
1652                         {
1653                                 if (tdb)
1654                                         MarkRelocatable(cursect, sloc, tdb, MLONG, NULL);
1655
1656                                 D_long(eval);
1657                         }
1658
1659                         break;
1660                 }
1661         }
1662
1663         return 0;
1664 }
1665
1666
1667 //
1668 // .comm symbol, size
1669 //
1670 int d_comm(void)
1671 {
1672         SYM * sym;
1673         char * p;
1674         uint64_t eval;
1675
1676         if (m6502)
1677                 return error(in_6502mode);
1678
1679         if (*tok != SYMBOL)
1680                 return error("missing symbol");
1681
1682         p = string[tok[1]];
1683         tok += 2;
1684
1685         if (*p == '.')                                          // Cannot .comm a local symbol
1686                 return error(locgl_error);
1687
1688         if ((sym = lookup(p, LABEL, 0)) == NULL)
1689                 sym = NewSymbol(p, LABEL, 0);
1690         else
1691         {
1692                 if (sym->sattr & DEFINED)
1693                         return error(".comm symbol already defined");
1694         }
1695
1696         sym->sattr = GLOBAL | COMMON | BSS;
1697
1698         if (*tok++ != ',')
1699                 return error(comma_error);
1700
1701         if (abs_expr(&eval) != OK)                      // Parse size of common region
1702                 return 0;
1703
1704         sym->svalue = eval;                                     // Install common symbol's size
1705         ErrorIfNotAtEOL();
1706         return 0;
1707 }
1708
1709
1710 //
1711 // .list - Turn listing on
1712 //
1713 int d_list(void)
1714 {
1715         if (list_flag)
1716                 listing++;
1717
1718         return 0;
1719 }
1720
1721
1722 //
1723 // .nlist - Turn listing off
1724 //
1725 int d_nlist(void)
1726 {
1727         if (list_flag)
1728                 listing--;
1729
1730         return 0;
1731 }
1732
1733
1734 //
1735 // .68000 - Back to 68000 TEXT segment
1736 //
1737 int d_68000(void)
1738 {
1739         rgpu = rdsp = robjproc = dsp56001 = 0;
1740         // Switching from gpu/dsp sections should reset any ORG'd Address
1741         orgactive = 0;
1742         orgwarning = 0;
1743         SaveSection();
1744         SwitchSection(TEXT);
1745         activecpu = CPU_68000;
1746         return 0;
1747 }
1748
1749
1750 //
1751 // .68020 - Back to 68000 TEXT segment and select 68020
1752 //
1753 int d_68020(void)
1754 {
1755         d_68000();
1756         activecpu = CPU_68020;
1757         return 0;
1758 }
1759
1760
1761 //
1762 // .68030 - Back to 68000 TEXT segment and select 68030
1763 //
1764 int d_68030(void)
1765 {
1766         d_68000();
1767         activecpu = CPU_68030;
1768         return 0;
1769 }
1770
1771
1772 //
1773 // .68040 - Back to 68000 TEXT segment and select 68040
1774 //
1775 int d_68040(void)
1776 {
1777         d_68000();
1778         activecpu = CPU_68040;
1779         activefpu = FPU_68040;
1780         return 0;
1781 }
1782
1783
1784 //
1785 // .68060 - Back to 68000 TEXT segment and select 68060
1786 //
1787 int d_68060(void)
1788 {
1789         d_68000();
1790         activecpu = CPU_68060;
1791         activefpu = FPU_68060;
1792         return 0;
1793 }
1794
1795
1796 //
1797 // .68881 - Back to 680x0 TEXT segment and select 68881 FPU
1798 //
1799 int d_68881(void)
1800 {
1801         //d_68000();
1802         activefpu = FPU_68881;
1803         return 0;
1804 }
1805
1806
1807 //
1808 // .68882 - Back to 680x0 TEXT segment and select 68882 FPU
1809 //
1810 int d_68882(void)
1811 {
1812         //d_68000();
1813         activefpu = FPU_68882;
1814         return 0;
1815 }
1816
1817
1818 //
1819 // nofpu - Deselect FPUs.
1820 //
1821 int d_nofpu(void)
1822 {
1823         activefpu = FPU_NONE;
1824         return 0;
1825 }
1826
1827
1828 //
1829 // .56001 - Switch to DSP56001 assembler
1830 //
1831 int d_56001(void)
1832 {
1833         dsp56001 = 1;
1834         rgpu = rdsp = robjproc = 0;
1835         SaveSection();
1836
1837         if ((obj_format == LOD) || (obj_format == P56))
1838                 SwitchSection(M56001P);
1839
1840         return 0;
1841 }
1842
1843
1844 //
1845 // .gpu - Switch to GPU assembler
1846 //
1847 int d_gpu(void)
1848 {
1849         if ((cursect != TEXT) && (cursect != DATA))
1850         {
1851                 error(".gpu can only be used in the TEXT or DATA segments");
1852                 return ERROR;
1853         }
1854
1855         // If previous section was DSP or 68000 then we need to reset ORG'd Addresses
1856         if (!rgpu)
1857         {
1858                 orgactive = 0;
1859                 orgwarning = 0;
1860         }
1861
1862         rgpu = 1;                       // Set GPU assembly
1863         rdsp = 0;                       // Unset DSP assembly
1864         robjproc = 0;           // Unset OP assembly
1865         dsp56001 = 0;           // Unset 56001 assembly
1866         regbank = BANK_N;       // Set no default register bank
1867         return 0;
1868 }
1869
1870
1871 //
1872 // .dsp - Switch to DSP assembler
1873 //
1874 int d_dsp(void)
1875 {
1876         if ((cursect != TEXT) && (cursect != DATA))
1877         {
1878                 error(".dsp can only be used in the TEXT or DATA segments");
1879                 return ERROR;
1880         }
1881
1882         // If previous section was gpu or 68000 then we need to reset ORG'd Addresses
1883         if (!rdsp)
1884         {
1885                 orgactive = 0;
1886                 orgwarning = 0;
1887         }
1888
1889         rdsp = 1;                       // Set DSP assembly
1890         rgpu = 0;                       // Unset GPU assembly
1891         robjproc = 0;           // Unset OP assembly
1892         dsp56001 = 0;           // Unset 56001 assembly
1893         regbank = BANK_N;       // Set no default register bank
1894         return 0;
1895 }
1896
1897
1898 //
1899 // .cargs [#offset], symbol[.size], ...
1900 //
1901 // Lists of registers may also be mentioned; they just take up space. Good for
1902 // "documentation" purposes:
1903 //
1904 // .cargs a6, .arg1, .arg2, .arg3...
1905 //
1906 // Symbols thus created are ABS and EQUATED.
1907 //
1908 int d_cargs(void)
1909 {
1910         uint64_t eval = 4;      // Default to 4 if no offset specified (to account for
1911                                                 // return address)
1912         WORD rlist;
1913         SYM * symbol;
1914         char * p;
1915         int env;
1916         int i;
1917
1918         if (rgpu || rdsp)
1919                 return error("directive forbidden in gpu/dsp mode");
1920
1921         if (*tok == '#')
1922         {
1923                 tok++;
1924
1925                 if (abs_expr(&eval) != OK)
1926                         return 0;
1927
1928                 // Eat the comma, if it's there
1929                 if (*tok == ',')
1930                         tok++;
1931         }
1932
1933         for(;;)
1934         {
1935                 if (*tok == SYMBOL)
1936                 {
1937                         p = string[tok[1]];
1938
1939                         // Set env to either local (dot prefixed) or global scope
1940                         env = (*p == '.' ? curenv : 0);
1941                         symbol = lookup(p, LABEL, env);
1942
1943                         if (symbol == NULL)
1944                         {
1945                                 symbol = NewSymbol(p, LABEL, env);
1946                                 symbol->sattr = 0;
1947                         }
1948                         else if (symbol->sattr & DEFINED)
1949                                 return error("multiply-defined label '%s'", p);
1950
1951                         // Put symbol in "order of definition" list
1952                         AddToSymbolDeclarationList(symbol);
1953
1954                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1955                         symbol->svalue = eval;
1956                         tok += 2;
1957
1958                         // What this does is eat any dot suffixes attached to a symbol. If
1959                         // it's a .L, it adds 4 to eval; if it's .W or .B, it adds 2. If
1960                         // there is no dot suffix, it assumes a size of 2.
1961                         switch ((int)*tok)
1962                         {
1963                         case DOTL:
1964                                 eval += 2;
1965                         case DOTB:
1966                         case DOTW:
1967                                 tok++;
1968                         }
1969
1970                         eval += 2;
1971                 }
1972                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1973                 {
1974                         if (reglist(&rlist) < 0)
1975                                 return 0;
1976
1977                         for(i=0; i<16; i++, rlist>>=1)
1978                         {
1979                                 if (rlist & 1)
1980                                         eval += 4;
1981                         }
1982                 }
1983                 else
1984                 {
1985                         switch ((int)*tok)
1986                         {
1987                         case KW_USP:
1988                         case KW_SSP:
1989                         case KW_PC:
1990                                 eval += 2;
1991                                 // FALLTHROUGH
1992                         case KW_SR:
1993                         case KW_CCR:
1994                                 eval += 2;
1995                                 tok++;
1996                                 break;
1997                         case EOL:
1998                                 return 0;
1999                         default:
2000                                 return error(".cargs syntax");
2001                         }
2002                 }
2003
2004                 // Eat commas in between each argument, if they exist
2005                 if (*tok == ',')
2006                         tok++;
2007         }
2008 }
2009
2010
2011 //
2012 // .cstruct [#offset], symbol[.size], ...
2013 //
2014 // Lists of registers may also be mentioned; they just take up space. Good for
2015 // "documentation" purposes:
2016 //
2017 // .cstruct a6, .arg1, .arg2, .arg3...
2018 //
2019 // Symbols thus created are ABS and EQUATED. Note that this is for
2020 // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for
2021 // the suggestion.
2022 //
2023 int d_cstruct(void)
2024 {
2025         uint64_t eval = 0;      // Default, if no offset specified, is zero
2026         WORD rlist;
2027         SYM * symbol;
2028         char * symbolName;
2029         int env;
2030         int i;
2031
2032         if (rgpu || rdsp)
2033                 return error("directive forbidden in gpu/dsp mode");
2034
2035         if (*tok == '#')
2036         {
2037                 tok++;
2038
2039                 if (abs_expr(&eval) != OK)
2040                         return 0;
2041
2042                 // Eat the comma, if it's there
2043                 if (*tok == ',')
2044                         tok++;
2045         }
2046
2047         for(;;)
2048         {
2049                 if (*tok == SYMBOL)
2050                 {
2051                         symbolName = string[tok[1]];
2052
2053                         // Set env to either local (dot prefixed) or global scope
2054                         env = (symbolName[0] == '.' ? curenv : 0);
2055                         symbol = lookup(symbolName, LABEL, env);
2056
2057                         // If the symbol wasn't found, then define it. Otherwise, throw an
2058                         // error.
2059                         if (symbol == NULL)
2060                         {
2061                                 symbol = NewSymbol(symbolName, LABEL, env);
2062                                 symbol->sattr = 0;
2063                         }
2064                         else if (symbol->sattr & DEFINED)
2065                                 return error("multiply-defined label '%s'", symbolName);
2066
2067                         // Put symbol in "order of definition" list
2068                         AddToSymbolDeclarationList(symbol);
2069
2070                         tok += 2;
2071
2072                         // Adjust label start address if it's a word or a long, as a byte
2073                         // label might have left us on an odd address.
2074                         switch ((int)*tok)
2075                         {
2076                         case DOTW:
2077                         case DOTL:
2078                                 eval += eval & 0x01;
2079                         }
2080
2081                         symbol->sattr |= (ABS | DEFINED | EQUATED);
2082                         symbol->svalue = eval;
2083
2084                         // Check for dot suffixes and adjust space accordingly (longs and
2085                         // words on an odd boundary get bumped to the next word aligned
2086                         // address). If no suffix, then throw an error.
2087                         switch ((int)*tok)
2088                         {
2089                         case DOTL:
2090                                 eval += 4;
2091                                 break;
2092                         case DOTW:
2093                                 eval += 2;
2094                                 break;
2095                         case DOTB:
2096                                 eval += 1;
2097                                 break;
2098                         default:
2099                                 return error("Symbol missing dot suffix in .cstruct construct");
2100                         }
2101
2102                         tok++;
2103                 }
2104                 else if (*tok >= KW_D0 && *tok <= KW_A7)
2105                 {
2106                         if (reglist(&rlist) < 0)
2107                                 return 0;
2108
2109                         for(i=0; i<16; i++, rlist>>=1)
2110                         {
2111                                 if (rlist & 1)
2112                                         eval += 4;
2113                         }
2114                 }
2115                 else
2116                 {
2117                         switch ((int)*tok)
2118                         {
2119                         case KW_USP:
2120                         case KW_SSP:
2121                         case KW_PC:
2122                                 eval += 2;
2123                                 // FALLTHROUGH
2124                         case KW_SR:
2125                         case KW_CCR:
2126                                 eval += 2;
2127                                 tok++;
2128                                 break;
2129                         case EOL:
2130                                 return 0;
2131                         default:
2132                                 return error(".cstruct syntax");
2133                         }
2134                 }
2135
2136                 // Eat commas in between each argument, if they exist
2137                 if (*tok == ',')
2138                         tok++;
2139         }
2140 }
2141
2142
2143 //
2144 // Define start of OP object list (allows the use of ORG)
2145 //
2146 int d_objproc(void)
2147 {
2148         if ((cursect != TEXT) && (cursect != DATA))
2149         {
2150                 error(".objproc can only be used in the TEXT or DATA segments");
2151                 return ERROR;
2152         }
2153
2154         // If previous section was DSP or 68000 then we need to reset ORG'd
2155         // Addresses
2156         if (!robjproc)
2157         {
2158                 orgactive = 0;
2159                 orgwarning = 0;
2160         }
2161
2162         robjproc = 1;           // Set OP assembly
2163         rgpu = 0;                       // Unset GPU assembly
2164         rdsp = 0;                       // Unset DSP assembly
2165         dsp56001 = 0;           // Unset 56001 assembly
2166         return OK;
2167 }
2168
2169
2170 //
2171 // Undefine a macro - .undefmac macname [, macname...]
2172 //
2173 int undmac1(char * p)
2174 {
2175         SYM * symbol = lookup(p, MACRO, 0);
2176
2177         // If the macro symbol exists, cause it to disappear
2178         if (symbol != NULL)
2179                 symbol->stype = (BYTE)SY_UNDEF;
2180
2181         return OK;
2182 }
2183
2184
2185 int d_undmac(void)
2186 {
2187         symlist(undmac1);
2188         return 0;
2189 }
2190
2191
2192 int d_jpad(void)
2193 {
2194         warn("JPAD directive is deprecated/non-functional");
2195         return OK;
2196 }
2197
2198
2199 int d_nojpad(void)
2200 {
2201         warn("NOJPAD directive is deprecated/non-functional");
2202         return OK;
2203 }
2204
2205
2206 int d_gpumain(void)
2207 {
2208         return error("What the hell? Do you think we adhere to the Goof standard?");
2209 }
2210
2211
2212 //
2213 // .opt - turn a specific (or all) optimisation on or off
2214 //
2215 int d_opt(void)
2216 {
2217         while (*tok != EOL)
2218         {
2219                 if (*tok == STRING)
2220                 {
2221                         tok++;
2222                         char * tmpstr = string[*tok++];
2223
2224                         if (ParseOptimization(tmpstr) != OK)
2225                                 return error("unknown optimization flag '%s'", tmpstr);
2226                 }
2227                 else
2228                         return error(".opt directive needs every switch enclosed inside quotation marks");
2229         }
2230
2231         return OK;
2232 }
2233
2234
2235 //
2236 // .if, Start conditional assembly
2237 //
2238 int d_if(void)
2239 {
2240         WORD eattr;
2241         uint64_t eval;
2242         SYM * esym;
2243         IFENT * rif = f_ifent;
2244
2245         // Alloc an IFENTRY
2246         if (rif == NULL)
2247                 rif = (IFENT *)malloc(sizeof(IFENT));
2248         else
2249                 f_ifent = rif->if_prev;
2250
2251         rif->if_prev = ifent;
2252         ifent = rif;
2253
2254         if (!disabled)
2255         {
2256                 if (expr(exprbuf, &eval, &eattr, &esym) != OK)
2257                         return 0;
2258
2259                 if ((eattr & DEFINED) == 0)
2260                         return error(undef_error);
2261
2262                 disabled = !eval;
2263         }
2264
2265         rif->if_state = (WORD)disabled;
2266         return 0;
2267 }
2268
2269
2270 //
2271 // .else, Do alternate case for .if
2272 //
2273 int d_else(void)
2274 {
2275         IFENT * rif = ifent;
2276
2277         if (rif->if_prev == NULL)
2278                 return error("mismatched .else");
2279
2280         if (disabled)
2281                 disabled = rif->if_prev->if_state;
2282         else
2283                 disabled = 1;
2284
2285         rif->if_state = (WORD)disabled;
2286         return 0;
2287 }
2288
2289
2290 //
2291 // .endif, End of conditional assembly block
2292 // This is also called by fpop() to pop levels of IFENTs in case a macro or
2293 // include file exits early with `exitm' or `end'.
2294 //
2295 int d_endif(void)
2296 {
2297         IFENT * rif = ifent;
2298
2299         if (rif->if_prev == NULL)
2300                 return error("mismatched .endif");
2301
2302         ifent = rif->if_prev;
2303         disabled = rif->if_prev->if_state;
2304         rif->if_prev = f_ifent;
2305         f_ifent = rif;
2306         return 0;
2307 }
2308