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