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