New directive: PRGFLAGS sets GEMDOS PRG flags (such as Fastload, etc)
[rmac] / direct.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // DIRECT.C - Directive Handling
4 // Copyright (C) 199x Landon Dyer, 2011 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 "sect.h"
11 #include "riscasm.h"
12 #include "error.h"
13 #include "token.h"
14 #include "procln.h"
15 #include "expr.h"
16 #include "mach.h"
17 #include "listing.h"
18 #include "mark.h"
19 #include "symbol.h"
20
21 #define DEF_KW
22 #include "kwtab.h"
23
24
25 TOKEN exprbuf[128];                     // Expression buffer
26 SYM * symbolPtr[1000000];       // Symbol pointers table
27 static long unused;                     // For supressing 'write' warnings
28 char buffer[256];                       // Scratch buffer for messages
29
30
31 // Directive handler table
32 int (*dirtab[])() = {
33         d_org,                          // 0 org
34         d_even,                         // 1 even
35         d_unimpl,                       // 2 .6502
36         d_68000,                        // 3 .68000
37         d_bss,                          // 4 bss
38         d_data,                         // 5 data
39         d_text,                         // 6 text
40         d_abs,                          // 7 abs
41         d_comm,                         // 8 comm
42         (void *)d_init,         // 9 init
43         d_cargs,                        // 10 cargs
44         (void *)d_goto,         // 11 goto
45         (void *)d_dc,           // 12 dc
46         (void *)d_ds,           // 13 ds
47         d_undmac,                       // 14 undefmac
48         d_gpu,                          // 15 .gpu
49         d_dsp,                          // 16 .dsp
50         (void *)d_dcb,          // 17 dcb
51         d_unimpl,                       // 18* set
52         d_unimpl,                       // 19* reg
53         d_unimpl,                       // 20 dump
54         d_incbin,                       // 21 .incbin //load
55         d_unimpl,                       // 22 disable
56         d_unimpl,                       // 23 enable
57         d_globl,                        // 24 globl
58         d_regbank0,                     // 25 .regbank0
59         d_regbank1,                     // 26 .regbank1
60         d_unimpl,                       // 27 xdef
61         d_assert,                       // 28 assert
62         d_unimpl,                       // 29* if
63         d_unimpl,                       // 30* endif
64         d_unimpl,                       // 31* endc
65         d_unimpl,                       // 32* iif
66         d_include,                      // 33 include
67         fpop,                           // 34 end
68         d_unimpl,                       // 35* macro
69         ExitMacro,                      // 36* exitm
70         d_unimpl,                       // 37* endm
71         d_list,                         // 38 list
72         d_nlist,                        // 39 nlist
73         d_long,                         // 40* rept
74         d_phrase,                       // 41* endr
75         d_dphrase,                      // 42 struct
76         d_qphrase,                      // 43 ends
77         d_title,                        // 44 title
78         d_subttl,                       // 45 subttl
79         eject,                          // 46 eject
80         d_unimpl,                       // 47 error
81         d_unimpl,                       // 48 warn
82         d_noclear,                      // 49 .noclear
83         d_equrundef,            // 50 .equrundef/.regundef
84         d_ccundef,                      // 51 .ccundef
85         d_print,                        // 52 .print
86         d_cstruct,                      // 53 .cstruct
87         d_jpad,                         // 54 .jpad (deprecated)
88         d_nojpad,                       // 55 .nojpad (deprecated)
89         d_gpumain,                      // 56 .gpumain (deprecated)
90         d_prgflags,                     // 57 .prgflags
91 };
92
93
94 //
95 // .org - Set origin
96 //
97 int d_org(void)
98 {
99         VALUE address;
100
101         if (!rgpu && !rdsp) 
102                 return error(".org permitted only in gpu/dsp section");
103
104         orgaddr = 0;
105
106         if (abs_expr(&address) == ERROR)
107         {
108                 error("cannot determine org'd address");
109                 return ERROR;
110         }
111
112         orgaddr = address;
113         orgactive = 1;
114 //printf("ORG: address = $%08X...\n", orgaddr);
115
116         return 0;
117 }
118
119
120 //
121 // Print directive
122 //
123 int d_print(void)
124 {
125         char prntstr[LNSIZ];            // String for PRINT directive
126         char format[LNSIZ];                     // Format for PRINT directive
127         int formatting = 0;                     // Formatting on/off
128         int wordlong = 0;                       // WORD = 0, LONG = 1
129         int outtype = 0;                        // 0:hex, 1:decimal, 2:unsigned
130
131         VALUE eval;                                     // Expression value
132         WORD eattr;                                     // Expression attributes
133         SYM * esym;                                     // External symbol involved in expr.
134         TOKEN r_expr[EXPRSIZE];
135
136         while (*tok != EOL)
137         {
138                 switch(*tok)
139                 {
140                 case STRING:
141                         sprintf(prntstr, "%s", string[tok[1]]);
142                         printf("%s", prntstr);
143
144                         if (list_fd) 
145                                 unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
146
147                         tok += 2;
148                         break;
149                 case '/':
150                         formatting = 1;
151
152                         if (tok[1] != SYMBOL)
153                                 goto token_err;
154
155 //                      strcpy(prntstr, (char *)tok[2]);
156                         strcpy(prntstr, string[tok[2]]);
157
158                         switch(prntstr[0])
159                         {
160                         case 'l': case 'L': wordlong = 1; break;
161                         case 'w': case 'W': wordlong = 0; break;
162                         case 'x': case 'X': outtype  = 0; break;
163                         case 'd': case 'D': outtype  = 1; break;
164                         case 'u': case 'U': outtype  = 2; break;
165                         default:
166                                 error("unknown print format flag");
167                                 return ERROR;
168                         }
169
170                         tok += 3;
171                         break;
172                 case ',':
173                         tok++;
174                         break;
175                 default:
176                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
177                                 goto token_err;
178                         else
179                         {
180                                 switch(outtype)
181                                 {
182                                 case 0: strcpy(format, "%X"); break; 
183                                 case 1: strcpy(format, "%d" ); break; 
184                                 case 2: strcpy(format, "%u" ); break; 
185                                 }
186
187                                 if (wordlong)
188                                         sprintf(prntstr, format, eval);
189                                 else
190                                         sprintf(prntstr, format, eval & 0xFFFF);
191
192                                 printf("%s", prntstr);
193
194                                 if (list_fd) 
195                                         unused = write(list_fd, prntstr, (LONG)strlen(prntstr));
196
197                                 formatting = 0;
198                                 wordlong = 0;
199                                 outtype = 0;
200                         }
201
202                         break;
203                 }
204         }
205
206         printf("\n");
207
208         return 0;
209
210 token_err:
211         error("illegal print token");
212         return ERROR;
213 }
214
215
216 //
217 // Undefine an equated condition code
218 //
219 int d_ccundef(void)
220 {
221         SYM * ccname;
222
223         // Check that we are in a RISC section
224         if (!rgpu && !rdsp)
225         {
226                 error(".ccundef must be defined in .gpu/.dsp section");
227                 return ERROR;
228         }
229
230         if (*tok != SYMBOL)
231         {
232                 error("syntax error; expected symbol");
233                 return ERROR;
234         }
235
236         ccname = lookup(string[tok[1]], LABEL, 0);
237
238         // Make sure symbol is a valid ccdef
239         if (!ccname || !(ccname->sattre & EQUATEDCC))
240         {
241                 error("invalid equated condition name specified");
242                 return ERROR;
243         }
244
245         ccname->sattre |= UNDEF_CC;
246
247         return 0;
248 }
249
250
251 //
252 // Undefine an equated register
253 //
254 int d_equrundef(void)
255 {
256         SYM * regname;
257
258         // Check that we are in a RISC section
259         if (!rgpu && !rdsp)
260                 return error(".equrundef/.regundef must be defined in .gpu/.dsp section");
261
262         while (*tok != EOL)
263         {
264                 // Skip preceeding or seperating commas (if any)
265                 if (*tok == ',')
266                         tok++;
267
268                 // Check we are dealing with a symbol
269                 if (*tok != SYMBOL)
270                         return error("syntax error; expected symbol");
271
272                 // Lookup and undef if equated register
273                 regname = lookup(string[tok[1]], LABEL, 0);
274
275                 if (regname && (regname->sattre & EQUATEDREG))
276                 {
277                         // Reset the attributes of this symbol...
278                         regname->sattr = 0;
279                         regname->sattre &= ~(EQUATEDREG | BANK_0 | BANK_1);
280                         regname->sattre |= UNDEF_EQUR;
281                 }
282
283                 // Skip over symbol token and address
284                 tok += 2;
285         }
286
287         return 0;
288 }
289
290
291 //
292 // Do not allow use of the CLR.L opcode
293 //
294 int d_noclear(void)
295 {
296         warn("CLR.L opcode ignored...");
297         return 0;
298 }
299
300
301 // 
302 // Include binary file
303 //
304 int d_incbin(void)
305 {
306         int fd;
307         int bytes = 0;
308         long pos, size, bytesRead;
309         char msg[256];
310
311         // Check to see if we're in BSS, and, if so, throw an error
312         if (scattr & SBSS)
313         {
314                 errors("cannot include binary file \"%s\" in BSS section", string[tok[1]]);
315                 return ERROR;
316         }
317
318         if (*tok != STRING)
319         {
320                 error("syntax error; string missing");
321                 return ERROR;
322         }
323
324         if ((fd = open(string[tok[1]],  _OPEN_INC)) < 0)
325         {
326                 errors("cannot open include binary file (%s)", string[tok[1]]);
327                 return ERROR;
328         }
329
330         size = lseek(fd, 0L, SEEK_END);
331         pos = lseek(fd, 0L, SEEK_SET);
332         chcheck(size);
333
334         DEBUG { printf("INCBIN: File '%s' is %li bytes.\n", string[tok[1]], size); }
335
336         char * fileBuffer = (char *)malloc(size);
337         bytesRead = read(fd, fileBuffer, size);
338
339         if (bytesRead != size)
340         {
341                 sprintf(msg, "was only able to read %li bytes from binary file (%s, %li bytes)", bytesRead, string[tok[1]], size);
342                 error(msg);
343                 return ERROR;
344         }
345
346         memcpy(chptr, fileBuffer, size);
347         chptr += size;
348         sloc += size;
349         ch_size += size;
350
351         if (orgactive)
352                 orgaddr += size;
353
354         free(fileBuffer);
355         close(fd);
356         return 0;
357 }
358
359
360 // 
361 // Set RISC register banks
362 //
363 int d_regbank0(void)
364 {
365         // Set active register bank zero
366         regbank = BANK_0;
367         return 0;
368 }
369
370
371 int d_regbank1(void)
372 {
373         // Set active register bank one
374         regbank = BANK_1;
375         return 0;
376 }
377
378
379 //
380 // Helper function, to cut down on mistakes & typing
381 //
382 static inline void SkipBytes(unsigned bytesToSkip)
383 {
384         if (!bytesToSkip)
385                 return;
386
387         if ((scattr & SBSS) == 0)
388         {
389                 chcheck(bytesToSkip);
390                 D_ZEROFILL(bytesToSkip);
391         }
392         else
393         {
394                 sloc += bytesToSkip;
395
396                 if (orgactive)
397                         orgaddr += bytesToSkip;
398         }
399 }
400
401
402 //
403 // Adjust location to an EVEN value
404 //
405 int d_even(void)
406 {
407         unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01;
408         
409         if (skip)
410         {
411                 if ((scattr & SBSS) == 0)
412                 {
413                         chcheck(1);
414                         D_byte(0);
415                 }
416                 else
417                 {
418                         sloc++;
419
420                         if (orgactive)
421                                 orgaddr++;
422                 }
423         }
424
425         return 0;
426 }
427
428
429 //
430 // Adjust location to a LONG value
431 //
432 int d_long(void)
433 {
434         unsigned lower2Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x03;
435         unsigned bytesToSkip = (0x04 - lower2Bits) & 0x03;
436         SkipBytes(bytesToSkip);
437
438         return 0;
439 }
440
441
442 //
443 // Adjust location to a PHRASE value
444 //
445 // N.B.: We have to handle the GPU/DSP cases separately because you can embed
446 //       RISC code in the middle of a regular 68K section. Also note that all
447 //       of the alignment pseudo-ops will have to be fixed this way.
448 //
449 // This *must* behave differently when in a RISC section, as following sloc
450 // (instead of orgaddr) will fuck things up royally. Note that we do it this
451 // way because you can embed RISC code in a 68K section, and have the origin
452 // pointing to a different alignment in the RISC section than the 68K section.
453 //
454 int d_phrase(void)
455 {
456         unsigned lower3Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x07;
457         unsigned bytesToSkip = (0x08 - lower3Bits) & 0x07;
458         SkipBytes(bytesToSkip);
459
460         return 0;
461 }
462
463
464 //
465 // Adjust location to a DPHRASE value
466 //
467 int d_dphrase(void)
468 {
469         unsigned lower4Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x0F;
470         unsigned bytesToSkip = (0x10 - lower4Bits) & 0x0F;
471         SkipBytes(bytesToSkip);
472
473         return 0;
474 }
475
476
477 //
478 // Adjust location to a QPHRASE value
479 //
480 int d_qphrase(void)
481 {
482         unsigned lower5Bits = (rgpu || rdsp ? orgaddr : sloc) & 0x1F;
483         unsigned bytesToSkip = (0x20 - lower5Bits) & 0x1F;
484         SkipBytes(bytesToSkip);
485
486         return 0;
487 }
488
489
490 //
491 // Do auto-even.  This must be called ONLY if 'sloc' is odd.
492 //
493 // This is made hairy because, if there was a label on the line, we also have
494 // to adjust its value. This won't work with more than one label on the line,
495 // which is OK since multiple labels are only allowed in AS68 kludge mode, and
496 // the C compiler is VERY paranoid and uses ".even" whenever it can
497 //
498 // N.B.: This probably needs the same fixes as above...
499 //
500 void auto_even(void)
501 {
502         if (scattr & SBSS)
503                 sloc++;                         // Bump BSS section
504         else
505                 D_byte(0);                      // Deposit 0.b in non-BSS
506
507         if (lab_sym != NULL)    // Bump label if we have to
508                 lab_sym->svalue++;
509 }
510
511
512 //
513 // Unimplemened directive error
514 //
515 int d_unimpl(void)
516 {
517         return error("unimplemented directive");
518 }
519
520
521 // 
522 // Return absolute (not TDB) and defined expression or return an error
523 //
524 int abs_expr(VALUE * a_eval)
525 {
526         WORD eattr;
527
528         if (expr(exprbuf, a_eval, &eattr, NULL) < 0)
529                 return ERROR;
530
531         if (!(eattr & DEFINED))
532                 return error(undef_error);
533
534         if (eattr & TDB)
535                 return error(rel_error);
536
537         return OK;
538 }
539
540
541 //
542 // Hand symbols in a symbol-list to a function (kind of like mapcar...)
543 //
544 int symlist(int(* func)())
545 {
546         const char * em = "symbol list syntax";
547
548         for(;;)
549         {
550                 if (*tok != SYMBOL)
551                         return error(em);
552
553                 if ((*func)(string[tok[1]]) != OK)
554                         break;
555
556                 tok += 2;
557
558                 if (*tok == EOL)
559                         break;
560
561                 if (*tok != ',')
562                         return error(em);
563
564                 tok++;
565         }
566
567         return 0;
568 }
569
570
571 //
572 // .include "filename"
573 //
574 int d_include(void)
575 {
576         int j;
577         int i;
578         char * fn;
579         char buf[128];
580         char buf1[128];
581
582         if (*tok == STRING)                     // Leave strings ALONE 
583                 fn = string[*++tok];
584         else if (*tok == SYMBOL)        // Try to append ".s" to symbols
585         {
586                 strcpy(buf, string[*++tok]);
587                 fext(buf, ".s", 0);
588                 fn = &buf[0];
589         }
590         else                                            // Punt if no STRING or SYMBOL 
591                 return error("missing filename");
592
593         // Make sure the user didn't try anything like:
594         // .include equates.s
595         if (*++tok != EOL)
596                 return error("extra stuff after filename -- enclose it in quotes");
597
598         // Attempt to open the include file in the current directory, then (if that
599         // failed) try list of include files passed in the enviroment string or by
600         // the "-d" option.
601         if ((j = open(fn, 0)) < 0)
602         {
603                 for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
604                 {
605                         j = strlen(buf1);
606
607                         if (j > 0 && buf1[j - 1] != SLASHCHAR)  // Append path char if necessary 
608                                 strcat(buf1, SLASHSTRING);
609
610                         strcat(buf1, fn);
611
612                         if ((j = open(buf1, 0)) >= 0)
613                                 goto allright;
614                 }
615
616                 return errors("cannot open: \"%s\"", fn);
617         }
618
619 allright:
620         include(j, fn);
621         return 0;
622 }
623
624
625 //
626 // .assert expression [, expression...]
627 //
628 int d_assert(void)
629 {
630         WORD eattr;
631         VALUE eval;
632
633         for(; expr(exprbuf, &eval, &eattr, NULL)==OK; ++tok)
634         {
635                 if (!(eattr & DEFINED))
636                         return error("forward or undefined .assert");
637
638                 if (!eval)
639                         return error("assert failure");
640
641                 if (*tok != ',')
642                         break;
643         }
644
645         at_eol();
646         return 0;
647 }
648
649
650 //
651 // .globl symbol [, symbol] <<<cannot make local symbols global>>>
652 //
653 int globl1(char * p)
654 {
655         SYM * sy;
656
657         if (*p == '.')
658                 return error("cannot .globl local symbol");
659
660         if ((sy = lookup(p, LABEL, 0)) == NULL)
661         {
662                 sy = NewSymbol(p, LABEL, 0);
663                 sy->svalue = 0;
664                 sy->sattr = GLOBAL;
665 //printf("glob1: Making global symbol: attr=%04X, eattr=%08X, %s\n", sy->sattr, sy->sattre, sy->sname);
666         }
667         else 
668                 sy->sattr |= GLOBAL;
669
670         return OK;
671 }
672
673
674 int d_globl(void)
675 {
676         symlist(globl1);
677         return 0;
678 }
679
680
681 //
682 // .prgflags expression
683 //
684 int d_prgflags(void)
685 {
686         VALUE eval;
687
688         if (*tok == EOL)
689                 return error("PRGFLAGS requires value");
690         else if (abs_expr(&eval) == OK)
691         {
692                 PRGFLAGS=eval;
693                 return 0;
694         }
695         else
696         {
697                 return error("PRGFLAGS requires value");
698         }
699 }
700
701
702 //
703 // .abs [expression]
704 //
705 int d_abs(void)
706 {
707         VALUE eval;
708
709         SaveSection();
710
711         if (*tok == EOL)
712                 eval = 0;
713         else if (abs_expr(&eval) != OK)
714                 return 0;
715
716         SwitchSection(ABS);
717         sloc = eval;
718         return 0;
719 }
720
721
722 //
723 // Switch segments
724 //
725 int d_text(void)
726 {
727         if (rgpu || rdsp)
728                 return error("directive forbidden in gpu/dsp mode");
729
730         if (cursect != TEXT)
731         {
732                 SaveSection();
733                 SwitchSection(TEXT);
734         }
735
736         return 0;
737 }
738
739
740 int d_data(void)
741 {
742         if (rgpu || rdsp)
743                 return error("directive forbidden in gpu/dsp mode");
744
745         if (cursect != DATA)
746         {
747                 SaveSection();
748                 SwitchSection(DATA);
749         }
750
751         return 0;
752 }
753
754
755 int d_bss(void)
756 {
757         if (rgpu || rdsp)
758                 return error("directive forbidden in gpu/dsp mode");
759
760         if (cursect != BSS)
761         {
762                 SaveSection();
763                 SwitchSection(BSS);
764         }
765
766         return 0;
767 }
768
769
770 //
771 // .ds[.size] expression
772 //
773 int d_ds(WORD siz)
774 {
775 if (verb_flag)
776         printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc);
777
778         VALUE eval;
779
780         // This gets kind of stupid.  This directive is disallowed in normal 68000
781         // mode ("for your own good!"), but is permitted for 6502 and Alcyon-
782         // compatibility modes. For obvious reasons, no auto-even is done in 8-bit
783         // processor modes.
784         if (as68_flag == 0 && (scattr & SBSS) == 0)
785                 return error(".ds permitted only in BSS");
786
787         if (siz != SIZB && (sloc & 1))                            // Automatic .even 
788                 auto_even();
789
790         if (abs_expr(&eval) != OK)
791                 return 0;
792
793         // In non-TDB section (BSS, ABS and M6502) just advance the location
794         // counter appropriately. In TDB sections, deposit (possibly large) chunks
795         //of zeroed memory....
796         if (scattr & SBSS)
797         {
798                 listvalue(eval);
799                 eval *= siz;
800                 sloc += eval;
801                 just_bss = 1;                                         // No data deposited (8-bit CPU mode)
802         }
803         else
804         {
805                 dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED | ABS), NULL);
806         }
807
808         at_eol();
809         return 0;
810 }
811
812
813 //
814 // dc.b, dc.w / dc, dc.l
815 //
816 int d_dc(WORD siz)
817 {
818         WORD eattr;
819         VALUE eval;
820         WORD tdb;
821         WORD defined;
822         LONG i;
823         char * p;
824         int movei = 0; // movei flag for dc.i
825
826         if ((scattr & SBSS) != 0)
827                 return error("illegal initialization of section");
828
829         // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???)
830         if ((siz != SIZB) && (sloc & 1))
831                 auto_even();
832
833         // Check to see if we're trying to set LONGS on a non 32-bit aligned
834         // address in a GPU or DSP section, in their local RAM
835         if ((siz == SIZL) && (orgaddr & 0x03)
836                 && ((rgpu && (orgaddr >= 0xF03000) && (orgaddr <= 0xF03FFFF))
837                 || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF))))
838                 warn("depositing LONGs on a non-long address in local RAM");
839
840         for(;; ++tok)
841         {
842                 // dc.b 'string' [,] ...
843                 if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL))
844                 {
845                         i = strlen(string[tok[1]]);
846
847                         if ((challoc - ch_size) < i) 
848                                 chcheck(i);
849
850                         for(p=string[tok[1]]; *p!=EOS; ++p)
851                                 D_byte(*p);
852
853                         tok += 2;
854                         goto comma;
855                 }
856
857                 if (*tok == 'I')
858                 {
859                         movei = 1;
860                         tok++;
861                         siz = SIZL;
862                 }
863
864                 // dc.x <expression>
865                 if (expr(exprbuf, &eval, &eattr, NULL) != OK)
866                         return 0;
867
868                 tdb = (WORD)(eattr & TDB);
869                 defined = (WORD)(eattr & DEFINED);
870
871                 if ((challoc - ch_size) < 4)
872                         chcheck(4);
873
874                 switch (siz)
875                 {
876                 case SIZB:
877                         if (!defined)
878                         {
879                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
880                                 D_byte(0);
881                         }
882                         else
883                         {
884                                 if (tdb)
885                                         return error("non-absolute byte value");
886
887                                 if (eval + 0x100 >= 0x200)
888                                 {
889                                         sprintf(buffer, "%s (value = $%X)", range_error, eval);
890                                         return error(buffer);
891                                 }
892
893                                 D_byte(eval);
894                         }
895
896                         break;
897                 case SIZW:
898                 case SIZN:
899                         if (!defined)
900                         {
901                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
902                                 D_word(0);
903                         }
904                         else
905                         {
906                                 if (tdb)
907                                         rmark(cursect, sloc, tdb, MWORD, NULL);
908
909                                 if (eval + 0x10000 >= 0x20000)
910                                         return error(range_error);
911
912                                 // Deposit 68000 or 6502 (byte-reversed) word 
913                                 D_word(eval);
914                         }
915
916                         break;
917                 case SIZL:
918                         if (!defined)
919                         {
920                                 if (movei)
921                                         AddFixup(FU_LONG | FU_MOVEI, sloc, exprbuf);
922                                 else
923                                         AddFixup(FU_LONG, sloc, exprbuf);
924
925                                 D_long(0);
926                         }
927                         else
928                         {
929                                 if (tdb)
930                                         rmark(cursect, sloc, tdb, MLONG, NULL);
931
932                                 if (movei) 
933                                         eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
934
935                                 D_long(eval);
936                         }
937                         break;
938                 }
939                 
940 comma:
941                 if (*tok != ',')
942                         break;
943         }
944
945         at_eol();
946         return 0;
947 }
948
949
950 //
951 // dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2'
952 //
953 int d_dcb(WORD siz)
954 {
955         VALUE evalc, eval;
956         WORD eattr;
957
958         if ((scattr & SBSS) != 0)
959                 return error("illegal initialization of section");
960
961         if (abs_expr(&evalc) != OK)
962                 return 0;
963
964         if (*tok++ != ',')
965                 return error("missing comma");
966
967         if (expr(exprbuf, &eval, &eattr, NULL) < 0)
968                 return 0;
969
970         if ((siz != SIZB) && (sloc & 1))
971                 auto_even();
972
973         dep_block(evalc, siz, eval, eattr, exprbuf);
974         return 0;
975 }
976
977
978 //
979 // Generalized initialization directive
980 // 
981 // .init[.siz] [#count,] expression [.size] , ...
982 // 
983 // The size suffix on the ".init" directive becomes the default size of the
984 // objects to deposit. If an item is preceeded with a sharp (immediate) sign
985 // and an expression, it specifies a repeat count. The value to be deposited
986 // may be followed by a size suffix, which overrides the default size.
987 //
988 int d_init(WORD def_siz)
989 {
990         VALUE count;
991         VALUE eval;
992         WORD eattr;
993         WORD siz;
994
995         if ((scattr & SBSS) != 0)
996                 return error(".init not permitted in BSS or ABS");
997
998         if (rgpu || rdsp)
999                 return error("directive forbidden in gpu/dsp mode");
1000
1001         for(;;)
1002         {
1003                 // Get repeat count (defaults to 1)
1004                 if (*tok == '#')
1005                 {
1006                         ++tok;
1007
1008                         if (abs_expr(&count) != OK)
1009                                 return 0;
1010
1011                         if (*tok++ != ',')
1012                                 return error(comma_error);
1013                 }
1014                 else
1015                         count = 1;
1016
1017                 // Evaluate expression to deposit
1018                 if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1019                         return 0;
1020
1021                 switch ((int)*tok++)
1022                 {                                 // Determine size of object to deposit
1023                 case DOTB: siz = SIZB; break;
1024                 case DOTW: siz = SIZB; break;
1025                 case DOTL: siz = SIZL; break;
1026                 default: 
1027                         siz = def_siz;
1028                         --tok;
1029                         break;
1030                 }
1031
1032                 dep_block(count, siz, eval, eattr, exprbuf);
1033
1034                 switch ((int)*tok)
1035                 {
1036                 case EOL:
1037                         return 0;
1038                 case ',':
1039                         ++tok;
1040                         continue;
1041                 default:
1042                         return error(comma_error);
1043                 }
1044         }
1045 }
1046
1047
1048 //
1049 // Deposit 'count' values of size 'siz' in the current (non-BSS) segment
1050 //
1051 int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf)
1052 {
1053         WORD tdb;
1054         WORD defined;
1055
1056         tdb = (WORD)(eattr & TDB);
1057         defined = (WORD)(eattr & DEFINED);
1058
1059         while (count--)
1060         {
1061                 if ((challoc - ch_size) < 4)
1062                         chcheck(4L);
1063
1064                 switch(siz)
1065                 {
1066                 case SIZB:
1067                         if (!defined)
1068                         {
1069                                 AddFixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1070                                 D_byte(0);
1071                         }
1072                         else
1073                         {
1074                                 if (tdb)
1075                                         return error("non-absolute byte value");
1076
1077                                 if (eval + 0x100 >= 0x200)
1078                                         return error(range_error);
1079
1080                                 D_byte(eval);
1081                         }
1082
1083                         break;
1084                 case SIZW:
1085                 case SIZN:
1086                         if (!defined)
1087                         {
1088                                 AddFixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1089                                 D_word(0);
1090                         }
1091                         else
1092                         {
1093                                 if (tdb)
1094                                         rmark(cursect, sloc, tdb, MWORD, NULL);
1095
1096                                 if (eval + 0x10000 >= 0x20000)
1097                                         return error(range_error);
1098
1099                                 // Deposit 68000 or 6502 (byte-reversed) word
1100                                 D_word(eval);
1101                         }
1102
1103                         break;
1104                 case SIZL:
1105                         if (!defined)
1106                         {
1107                                 AddFixup(FU_LONG, sloc, exprbuf);
1108                                 D_long(0);
1109                         }
1110                         else
1111                         {
1112                                 if (tdb)
1113                                         rmark(cursect, sloc, tdb, MLONG, NULL);
1114
1115                                 D_long(eval);
1116                         }
1117
1118                         break;
1119                 }
1120         }
1121
1122         return 0;
1123 }
1124
1125
1126 //
1127 // .comm symbol, size
1128 //
1129 int d_comm(void)
1130 {
1131         SYM * sym;
1132         char * p;
1133         VALUE eval;
1134
1135         if (*tok != SYMBOL)
1136                 return error("missing symbol");
1137
1138         p = string[tok[1]];
1139         tok += 2;
1140
1141         if (*p == '.')                                                  // Cannot .comm a local symbol
1142                 return error(locgl_error);
1143
1144         if ((sym = lookup(p, LABEL, 0)) == NULL)
1145                 sym = NewSymbol(p, LABEL, 0);
1146         else
1147         {
1148                 if (sym->sattr & DEFINED)
1149                         return error(".comm symbol already defined");
1150         }
1151
1152         sym->sattr = GLOBAL | COMMON | BSS;
1153
1154         if (*tok++ != ',')
1155                 return error(comma_error);
1156
1157         if (abs_expr(&eval) != OK)                              // Parse size of common region
1158                 return 0;
1159
1160         sym->svalue = eval;                                             // Install common symbol's size
1161         at_eol();
1162         return 0;
1163 }
1164
1165
1166 //
1167 // .list - Turn listing on
1168 //
1169 int d_list(void)
1170 {
1171         if (list_flag)
1172                 listing++;
1173
1174         return 0;
1175 }
1176
1177
1178 //
1179 // .nlist - Turn listing off
1180 //
1181 int d_nlist(void)
1182 {
1183         if (list_flag)
1184                 listing--;
1185
1186         return 0;
1187 }
1188
1189
1190 //
1191 // .68000 - Back to 68000 TEXT segment
1192 //
1193 int d_68000(void)
1194 {
1195         rgpu = rdsp = 0;
1196         // Switching from gpu/dsp sections should reset any ORG'd Address
1197         orgactive = 0;                               
1198         orgwarning = 0;
1199         SaveSection();
1200         SwitchSection(TEXT);
1201         return 0;
1202 }
1203
1204
1205 //
1206 // .gpu - Switch to GPU assembler
1207 //
1208 int d_gpu(void)
1209 {
1210         if ((cursect != TEXT) && (cursect != DATA))
1211         {
1212                 error(".gpu can only be used in the TEXT or DATA segments");
1213                 return ERROR;
1214         }
1215
1216         // If previous section was dsp or 68000 then we need to reset ORG'd Addresses
1217         if (!rgpu)
1218         {
1219 //printf("Resetting ORG...\n");
1220                 orgactive = 0;
1221                 orgwarning = 0;
1222         }
1223 //else printf("NOT resetting ORG!\n");
1224
1225         rgpu = 1;                       // Set GPU assembly
1226         rdsp = 0;                       // Unset DSP assembly
1227         regbank = BANK_N;       // Set no default register bank
1228         return 0;
1229 }
1230
1231
1232 //
1233 // .dsp - Switch to DSP assembler
1234 //
1235 int d_dsp(void)
1236 {
1237         if ((cursect != TEXT) && (cursect != DATA))
1238         {
1239                 error(".dsp can only be used in the TEXT or DATA segments");
1240                 return ERROR;
1241         }
1242
1243         // If previous section was gpu or 68000 then we need to reset ORG'd Addresses
1244         if (!rdsp)
1245         {
1246                 orgactive = 0;
1247                 orgwarning = 0;
1248         }
1249
1250         rdsp = 1;                       // Set DSP assembly
1251         rgpu = 0;                       // Unset GPU assembly
1252         regbank = BANK_N;       // Set no default register bank
1253         return 0;
1254 }
1255
1256
1257 //
1258 // .cargs [#offset], symbol[.size], ...
1259 // 
1260 // Lists of registers may also be mentioned; they just take up space. Good for
1261 // "documentation" purposes:
1262 // 
1263 // .cargs a6, .arg1, .arg2, .arg3...
1264 // 
1265 // Symbols thus created are ABS and EQUATED.
1266 //
1267 int d_cargs(void)
1268 {
1269         VALUE eval = 4;         // Default to 4 if no offset specified (to account for
1270                                                 // return address)
1271         WORD rlist;
1272         SYM * symbol;
1273         char * p;
1274         int env;
1275         int i;
1276
1277         if (rgpu || rdsp)
1278                 return error("directive forbidden in gpu/dsp mode");
1279
1280         if (*tok == '#')
1281         {
1282                 tok++;
1283
1284                 if (abs_expr(&eval) != OK)
1285                         return 0;
1286
1287                 // Eat the comma, if it's there
1288                 if (*tok == ',')
1289                         tok++;
1290         }
1291
1292         for(;;)
1293         {
1294                 if (*tok == SYMBOL)
1295                 {
1296                         p = string[tok[1]];
1297
1298                         // Set env to either local (dot prefixed) or global scope
1299                         env = (*p == '.' ? curenv : 0);
1300                         symbol = lookup(p, LABEL, env);
1301
1302                         if (symbol == NULL)
1303                         {
1304                                 symbol = NewSymbol(p, LABEL, env);
1305                                 symbol->sattr = 0;
1306                         }
1307                         else if (symbol->sattr & DEFINED)
1308                                 return errors("multiply-defined label '%s'", p);
1309
1310                         // Put symbol in "order of definition" list
1311                         AddToSymbolDeclarationList(symbol);
1312
1313                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1314                         symbol->svalue = eval;
1315                         tok += 2;
1316
1317                         // What this does is eat any dot suffixes attached to a symbol. If
1318                         // it's a .L, it adds 4 to eval; if it's .W or .B, it adds 2. If
1319                         // there is no dot suffix, it assumes a size of 2.
1320                         switch ((int)*tok)
1321                         {
1322                         case DOTL:
1323                                 eval += 2;
1324                         case DOTB:
1325                         case DOTW:
1326                                 tok++;
1327                         }
1328
1329                         eval += 2;
1330                 }
1331                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1332                 {
1333                         if (reglist(&rlist) < 0)
1334                                 return 0;
1335
1336                         for(i=0; i<16; i++, rlist>>=1)
1337                         {
1338                                 if (rlist & 1)
1339                                         eval += 4;
1340                         }
1341                 }
1342                 else
1343                 {
1344                         switch ((int)*tok)
1345                         {
1346                         case KW_USP:
1347                         case KW_SSP:
1348                         case KW_PC:
1349                                 eval += 2;
1350                                 // FALLTHROUGH
1351                         case KW_SR:
1352                         case KW_CCR:
1353                                 eval += 2;
1354                                 tok++;
1355                                 break;
1356                         case EOL:
1357                                 return 0;
1358                         default:
1359                                 return error(".cargs syntax");
1360                         }
1361                 }
1362
1363                 // Eat commas in between each argument, if they exist
1364                 if (*tok == ',')
1365                         tok++;
1366         }
1367 }
1368
1369
1370 //
1371 // .cstruct [#offset], symbol[.size], ...
1372 // 
1373 // Lists of registers may also be mentioned; they just take up space. Good for
1374 // "documentation" purposes:
1375 // 
1376 // .cstruct a6, .arg1, .arg2, .arg3...
1377 // 
1378 // Symbols thus created are ABS and EQUATED. Note that this is for
1379 // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for
1380 // the suggestion.
1381 //
1382 int d_cstruct(void)
1383 {
1384         VALUE eval = 0;         // Default, if no offset specified, is zero
1385         WORD rlist;
1386         SYM * symbol;
1387         char * symbolName;
1388         int env;
1389         int i;
1390
1391         if (rgpu || rdsp)
1392                 return error("directive forbidden in gpu/dsp mode");
1393
1394         if (*tok == '#')
1395         {
1396                 tok++;
1397
1398                 if (abs_expr(&eval) != OK)
1399                         return 0;
1400
1401                 // Eat the comma, if it's there
1402                 if (*tok == ',')
1403                         tok++;
1404         }
1405
1406         for(;;)
1407         {
1408                 if (*tok == SYMBOL)
1409                 {
1410                         symbolName = string[tok[1]];
1411
1412                         // Set env to either local (dot prefixed) or global scope
1413                         env = (symbolName[0] == '.' ? curenv : 0);
1414                         symbol = lookup(symbolName, LABEL, env);
1415
1416                         // If the symbol wasn't found, then define it. Otherwise, throw an
1417                         // error.
1418                         if (symbol == NULL)
1419                         {
1420                                 symbol = NewSymbol(symbolName, LABEL, env);
1421                                 symbol->sattr = 0;
1422                         }
1423                         else if (symbol->sattr & DEFINED)
1424                                 return errors("multiply-defined label '%s'", symbolName);
1425
1426                         // Put symbol in "order of definition" list
1427                         AddToSymbolDeclarationList(symbol);
1428
1429                         tok += 2;
1430
1431                         // Adjust label start address if it's a word or a long, as a byte
1432                         // label might have left us on an odd address.
1433                         switch ((int)*tok)
1434                         {
1435                         case DOTW:
1436                         case DOTL:
1437                                 eval += eval & 0x01;
1438                         }
1439
1440                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1441                         symbol->svalue = eval;
1442
1443                         // Check for dot suffixes and adjust space accordingly (longs and
1444                         // words on an odd boundary get bumped to the next word aligned
1445                         // address). If no suffix, then throw an error.
1446                         switch ((int)*tok)
1447                         {
1448                         case DOTL:
1449                                 eval += 4;
1450                                 break;
1451                         case DOTW:
1452                                 eval += 2;
1453                                 break;
1454                         case DOTB:
1455                                 eval += 1;
1456                                 break;
1457                         default:
1458                                 return error("Symbol missing dot suffix in .cstruct construct");
1459                         }
1460
1461                         tok++;
1462                 }
1463                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1464                 {
1465                         if (reglist(&rlist) < 0)
1466                                 return 0;
1467
1468                         for(i=0; i<16; i++, rlist>>=1)
1469                         {
1470                                 if (rlist & 1)
1471                                         eval += 4;
1472                         }
1473                 }
1474                 else
1475                 {
1476                         switch ((int)*tok)
1477                         {
1478                         case KW_USP:
1479                         case KW_SSP:
1480                         case KW_PC:
1481                                 eval += 2;
1482                                 // FALLTHROUGH
1483                         case KW_SR:
1484                         case KW_CCR:
1485                                 eval += 2;
1486                                 tok++;
1487                                 break;
1488                         case EOL:
1489                                 return 0;
1490                         default:
1491                                 return error(".cstruct syntax");
1492                         }
1493                 }
1494
1495                 // Eat commas in between each argument, if they exist
1496                 if (*tok == ',')
1497                         tok++;
1498         }
1499 }
1500
1501
1502 //
1503 // Undefine a macro - .undefmac macname [, macname...]
1504 //
1505 int undmac1(char * p)
1506 {
1507         SYM * symbol = lookup(p, MACRO, 0);
1508
1509         // If the macro symbol exists, cause it to disappear
1510 //      if ((sy = lookup(p, MACRO, 0)) != NULL)
1511         if (symbol != NULL)
1512                 symbol->stype = (BYTE)SY_UNDEF;
1513
1514         return OK;
1515 }
1516
1517
1518 int d_undmac(void)
1519 {
1520         symlist(undmac1);
1521         return 0;
1522 }
1523
1524
1525 int d_jpad(void)
1526 {
1527         warn("JPAD directive is deprecated/non-functional");
1528         return OK;
1529 }
1530
1531
1532 int d_nojpad(void)
1533 {
1534         warn("NOJPAD directive is deprecated/non-functional");
1535         return OK;
1536 }
1537
1538
1539 int d_gpumain(void)
1540 {
1541         return error("What the hell? Do you think we adhere to the Goof standard?");
1542 }
1543