Fix for slow .incbin performance.
[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 "risca.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
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 0
320         if ((j = open(string[tok[1]],  _OPEN_INC)) >= 0)
321         {
322                 size = lseek(j, 0L, SEEK_END);
323                 chcheck(size);
324                 pos = lseek(j, 0L, SEEK_SET);
325
326                 DEBUG
327                 {
328                         printf("INCBIN: File '%s' is %li bytes.\n", string[tok[1]], size);
329                 }
330
331                 for(i=0; i<size; i++)
332                 {
333                         buf = '\0';
334                         bytes = read(j, &buf, 1);
335                         D_byte(buf);
336                 }
337         }
338         else
339         {
340                 errors("cannot open include binary file (%s)", string[tok[1]]);
341                 return ERROR;
342         }
343 #else
344         if ((fd = open(string[tok[1]],  _OPEN_INC)) < 0)
345         {
346                 errors("cannot open include binary file (%s)", string[tok[1]]);
347                 return ERROR;
348         }
349
350         size = lseek(fd, 0L, SEEK_END);
351         pos = lseek(fd, 0L, SEEK_SET);
352         chcheck(size);
353
354         DEBUG
355         {
356                 printf("INCBIN: File '%s' is %li bytes.\n", string[tok[1]], size);
357         }
358
359 #if 0
360         for(i=0; i<size; i++)
361         {
362                 buf = '\0';
363                 bytes = read(j, &buf, 1);
364                 D_byte(buf);
365         }
366 #else
367         char * fileBuffer = (char *)malloc(size);
368         bytesRead = read(fd, fileBuffer, size);
369
370         if (bytesRead != size)
371         {
372                 sprintf(msg, "was only able to read %li bytes from binary file (%s, %li bytes)", bytesRead, string[tok[1]], size);
373                 error(msg);
374                 return ERROR;
375         }
376
377 //#define D_byte(b)    {*chptr++=(char)b; ++sloc; ++ch_size; if(orgactive) ++orgaddr;}
378         memcpy(chptr, fileBuffer, size);
379         chptr += size;
380         sloc += size;
381         ch_size += size;
382
383         if (orgactive)
384                 orgaddr += size;
385
386         free(fileBuffer);
387 #endif
388 #endif
389
390         close(fd);
391         return 0;
392 }
393
394
395 // 
396 // Set RISC Register Banks
397 //
398 int d_regbank0(void)
399 {
400         // Set active register bank zero
401         regbank = BANK_0;
402         return 0;
403 }
404
405
406 int d_regbank1(void)
407 {
408         // Set active register bank one
409         regbank = BANK_1;
410         return 0;
411 }
412
413
414 //
415 // Adjust Location to an EVEN Value
416 //
417 int d_even(void)
418 {
419         if (sloc & 1)
420         {
421                 if ((scattr & SBSS) == 0)
422                 {
423                         chcheck(1);
424                         D_byte(0);
425                 }
426                 else
427                 {
428                         ++sloc;
429                 }
430         }
431
432         return 0;
433 }
434
435
436 //
437 // Adjust Location to an LONG Value
438 //
439 int d_long(void)
440 {
441         unsigned i;
442         unsigned val = 4;
443                         
444         i = sloc & ~(val - 1);
445
446         if (i != sloc)
447                 val = val - (sloc - i); 
448         else
449                 val = 0;
450
451         if (val)
452         {
453                 if ((scattr & SBSS) == 0)
454                 {
455                         chcheck(val);
456
457                         for(i=0; i<val; i++) 
458                                 D_byte(0);
459                 }
460                 else
461                 {
462                         sloc += val;
463                 }
464         }
465
466         return 0;
467 }
468
469
470 //
471 // Adjust Location to an PHRASE Value
472 //
473 int d_phrase(void)
474 {
475         unsigned i;
476         unsigned val = 8;
477                         
478         i = sloc & ~(val - 1);
479
480         if (i != sloc)
481                 val = val - (sloc - i); 
482         else
483                 val = 0;
484
485         if (val)
486         {
487                 if ((scattr & SBSS) == 0)
488                 {
489                         chcheck(val);
490
491                         for(i=0; i<val; i++) 
492                                 D_byte(0);
493                 }
494                 else
495                 {
496                         sloc += val;
497                 }
498         }
499
500         return 0;
501 }
502
503
504 //
505 // Adjust Location to an DPHRASE Value
506 //
507 int d_dphrase(void)
508 {
509         unsigned i;
510         unsigned val = 16;
511                         
512         i = sloc & ~(val - 1);
513
514         if (i != sloc)
515                 val = val - (sloc - i); 
516         else
517                 val = 0;
518
519         if (val)
520         {
521                 if ((scattr & SBSS) == 0)
522                 {
523                         chcheck(val);
524
525                         for(i=0; i<val; i++) 
526                                 D_byte(0);
527                 }
528                 else
529                 {
530                         sloc += val;
531                 }
532         }
533
534         return 0;
535 }
536
537
538 //
539 // Adjust Location to an QPHRASE Value
540 //
541 int d_qphrase(void)
542 {
543         unsigned i;
544         unsigned val = 32;
545                         
546         i = sloc & ~(val - 1);
547
548         if (i != sloc)
549                 val = val - (sloc - i); 
550         else
551                 val = 0;
552
553         if (val)
554         {
555                 if ((scattr & SBSS) == 0)
556                 {
557                         savsect();
558                         chcheck(val);
559
560                         for(i=0; i<val; i++) 
561                                 D_byte(0);
562                 }
563                 else
564                 {
565                         sloc += val;
566                 }
567         }
568
569         return 0;
570 }
571
572
573 //
574 // Do auto-even.  This must be called ONLY if 'sloc' is odd.
575 //
576 // This is made hairy because, if there was a label on the line, we also have
577 // to adjust its value. This won't work with more than one label on the line,
578 // which is OK since multiple labels are only allowed in AS68 kludge mode, and
579 // the C compiler is VERY paranoid and uses ".even" whenever it can
580 //
581 void auto_even(void)
582 {
583         if (scattr & SBSS)
584                 ++sloc;                                               // Bump BSS section
585         else
586                 D_byte(0)                                             // Deposit 0.b in non-BSS
587
588         if (lab_sym != NULL)                                      // Bump label if we have to
589                 ++lab_sym->svalue;
590 }
591
592
593 //
594 // Unimplemened Directive Error
595 //
596 int d_unimpl(void)
597 {
598         return error("unimplemented directive");
599 }
600
601
602 // 
603 // Return absolute (not TDB) and defined expression or return an error
604 //
605 int abs_expr(VALUE * a_eval)
606 {
607         WORD eattr;
608
609         if (expr(exprbuf, a_eval, &eattr, NULL) < 0)
610                 return ERROR;
611
612         if (!(eattr & DEFINED))
613                 return error(undef_error);
614
615         if (eattr & TDB)
616                 return error(rel_error);
617
618         return OK;
619 }
620
621
622 //
623 // Hand symbols in a symbol-list to a function (kind of like mapcar...)
624 //
625 int symlist(int(* func)())
626 {
627         char * em = "symbol list syntax";
628
629         for(;;)
630         {
631                 if (*tok != SYMBOL)
632                         return error(em);
633
634 #if 0
635                 if ((*func)(tok[1]) != OK)
636 #else
637                 if ((*func)(string[tok[1]]) != OK)
638 #endif
639                         break;
640
641                 tok += 2;
642
643                 if (*tok == EOL)
644                         break;
645
646                 if (*tok != ',')
647                         return error(em);
648
649                 ++tok;
650         }
651
652         return 0;
653 }
654
655
656 //
657 // .include "filename"
658 //
659 int d_include(void)
660 {
661         int j;
662         int i;
663         char * fn;
664         char buf[128];
665         char buf1[128];
666
667         if (*tok == STRING)                                                     // Leave strings ALONE 
668 #if 0
669                 fn = (char *)*++tok;
670 #else
671                 fn = string[*++tok];
672 #endif
673         else if (*tok == SYMBOL)                                        // Try to append ".s" to symbols
674         {
675 #if 0
676                 strcpy(buf, (char *)*++tok);
677 #else
678                 strcpy(buf, string[*++tok]);
679 #endif
680                 fext(buf, ".s", 0);
681                 fn = &buf[0];
682         }
683         else                                                                            // Punt if no STRING or SYMBOL 
684                 return error("missing filename");
685
686         // Make sure the user didn't try anything like:
687         // .include equates.s
688         if (*++tok != EOL)
689                 return error("extra stuff after filename -- enclose it in quotes");
690
691         // Attempt to open the include file in the current directory, then (if that
692         // failed) try list of include files passed in the enviroment string or by
693         // the "-d" option.
694         if ((j = open(fn, 0)) < 0)
695         {
696                 for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
697                 {
698                         j = strlen(buf1);
699
700                         if (j > 0 && buf1[j - 1] != SLASHCHAR)  // Append path char if necessary 
701                                 strcat(buf1, SLASHSTRING);
702
703                         strcat(buf1, fn);
704
705                         if ((j = open(buf1, 0)) >= 0)
706                                 goto allright;
707                 }
708
709                 return errors("cannot open: \"%s\"", fn);
710         }
711
712 allright:
713         include(j, fn);
714         return 0;
715 }
716
717
718 //
719 // .assert expression [, expression...]
720 //
721 int d_assert(void)
722 {
723         WORD eattr;
724         VALUE eval;
725
726         for(; expr(exprbuf, &eval, &eattr, NULL)==OK; ++tok)
727         {
728                 if (!(eattr & DEFINED))
729                         return error("forward or undefined .assert");
730
731                 if (!eval)
732                         return error("assert failure");
733
734                 if (*tok != ',')
735                         break;
736         }
737
738         at_eol();
739         return 0;
740 }
741
742
743 //
744 // .globl symbol [, symbol] <<<cannot make local symbols global>>>
745 //
746 int globl1(char * p)
747 {
748         SYM *sy;
749
750         if (*p == '.')
751                 return error("cannot .globl local symbol");
752
753         if ((sy = lookup(p, LABEL, 0)) == NULL)
754         {
755                 sy = NewSymbol(p, LABEL, 0);
756                 sy->svalue = 0;
757                 sy->sattr = GLOBAL;
758         }
759         else 
760                 sy->sattr |= GLOBAL;
761
762         return OK;
763 }
764
765
766 int d_globl(void)
767 {
768         symlist(globl1);
769         return 0;
770 }
771
772
773 //
774 // .abs [expression]
775 //
776 int d_abs(void)
777 {
778         VALUE eval;
779
780         savsect();
781
782         if (*tok == EOL)
783                 eval = 0;
784         else if (abs_expr(&eval) != OK)
785                 return 0;
786
787         switchsect(ABS);
788         sloc = eval;
789         return 0;
790 }
791
792
793 //
794 // Switch Segments
795 //
796
797 int d_text(void)
798 {
799         if (rgpu || rdsp)
800                 return error("directive forbidden in gpu/dsp mode");
801
802         if (cursect != TEXT)
803         {
804                 savsect();
805                 switchsect(TEXT);
806         }
807
808         return 0;
809 }
810
811
812 int d_data(void)
813 {
814         if (rgpu || rdsp)
815                 return error("directive forbidden in gpu/dsp mode");
816
817         if (cursect != DATA)
818         {
819                 savsect();
820                 switchsect(DATA);
821         }
822
823         return 0;
824 }
825
826
827 int d_bss(void)
828 {
829         if (rgpu || rdsp)
830                 return error("directive forbidden in gpu/dsp mode");
831
832         if (cursect != BSS)
833         {
834                 savsect();
835                 switchsect(BSS);
836         }
837
838         return 0;
839 }
840
841
842 //
843 // .ds[.size] expression
844 //
845 int d_ds(WORD siz)
846 {
847 if (verb_flag)
848         printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc);
849
850         VALUE eval;
851
852         // This gets kind of stupid.  This directive is disallowed in normal 68000
853         // mode ("for your own good!"), but is permitted for 6502 and Alcyon-
854         // compatibility modes. For obvious reasons, no auto-even is done in 8-bit
855         // processor modes.
856         if (as68_flag == 0 && (scattr & SBSS) == 0)
857                 return error(".ds permitted only in BSS");
858
859         if (siz != SIZB && (sloc & 1))                            // Automatic .even 
860                 auto_even();
861
862         if (abs_expr(&eval) != OK)
863                 return 0;
864
865         // In non-TDB section (BSS, ABS and M6502) just advance the location
866         // counter appropriately. In TDB sections, deposit (possibly large) chunks
867         //of zeroed memory....
868         if (scattr & SBSS)
869         {
870                 listvalue(eval);
871                 eval *= siz;
872                 sloc += eval;
873                 just_bss = 1;                                         // No data deposited (8-bit CPU mode)
874         }
875         else
876         {
877                 dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED | ABS), NULL);
878         }
879
880         at_eol();
881         return 0;
882 }
883
884
885 //
886 // dc.b, dc.w / dc, dc.l
887 //
888 int d_dc(WORD siz)
889 {
890         WORD eattr;
891         VALUE eval;
892         WORD tdb;
893         WORD defined;
894         LONG i;
895         char * p;
896         int movei = 0; // movei flag for dc.i
897
898         if ((scattr & SBSS) != 0)
899                 return error("illegal initialization of section");
900
901         if ((siz != SIZB) && (sloc & 1))
902                 auto_even();
903
904         for(;; ++tok)
905         {
906                 // dc.b 'string' [,] ...
907                 if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL))
908                 {
909 //                      i = strlen((const char*)tok[1]);
910                         i = strlen(string[tok[1]]);
911
912                         if ((challoc - ch_size) < i) 
913                                 chcheck(i);
914
915                         for(p=string[tok[1]]; *p!=EOS; ++p)
916                                 D_byte(*p);
917
918                         tok += 2;
919                         goto comma;
920                 }
921
922                 if (*tok == 'I')
923                 {
924                         movei = 1;
925                         tok++;
926                         siz = SIZL;
927                 }
928
929                 // dc.x <expression>
930                 if (expr(exprbuf, &eval, &eattr, NULL) != OK)
931                         return 0;
932
933                 tdb = (WORD)(eattr & TDB);
934                 defined = (WORD)(eattr & DEFINED);
935
936                 if ((challoc - ch_size) < 4)
937                         chcheck(4);
938
939                 switch (siz)
940                 {
941                 case SIZB:
942                         if (!defined)
943                         {
944                                 fixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
945                                 D_byte(0);
946                         }
947                         else
948                         {
949                                 if (tdb)
950                                         return error("non-absolute byte value");
951
952                                 if (eval + 0x100 >= 0x200)
953                                         return error(range_error);
954
955                                 D_byte(eval);
956                         }
957
958                         break;
959                 case SIZW:
960                 case SIZN:
961                         if (!defined)
962                         {
963                                 fixup(FU_WORD | FU_SEXT, sloc, exprbuf);
964                                 D_word(0);
965                         }
966                         else
967                         {
968                                 if (tdb)
969                                         rmark(cursect, sloc, tdb, MWORD, NULL);
970
971                                 if (eval + 0x10000 >= 0x20000)
972                                         return error(range_error);
973
974                                 // Deposit 68000 or 6502 (byte-reversed) word 
975                                 D_word(eval);
976                         }
977
978                         break;
979                 case SIZL:
980                         if (!defined)
981                         {
982                                 if (movei)
983                                         fixup(FU_LONG | FU_MOVEI, sloc, exprbuf);
984                                 else
985                                         fixup(FU_LONG, sloc, exprbuf);
986
987                                 D_long(0);
988                         }
989                         else
990                         {
991                                 if (tdb)
992                                         rmark(cursect, sloc, tdb, MLONG, NULL);
993
994                                 if (movei) 
995                                         eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
996
997                                 D_long(eval);
998                         }
999                         break;
1000                 }
1001                 
1002 comma:
1003                 if (*tok != ',')
1004                         break;
1005         }
1006
1007         at_eol();
1008         return 0;
1009 }
1010
1011
1012 //
1013 // dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2'
1014 //
1015 int d_dcb(WORD siz)
1016 {
1017         VALUE evalc, eval;
1018         WORD eattr;
1019
1020         if ((scattr & SBSS) != 0)
1021                 return error("illegal initialization of section");
1022
1023         if (abs_expr(&evalc) != OK)
1024                 return 0;
1025
1026         if (*tok++ != ',')
1027                 return error("missing comma");
1028
1029         if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1030                 return 0;
1031
1032         if ((siz != SIZB) && (sloc & 1))
1033                 auto_even();
1034
1035         dep_block(evalc, siz, eval, eattr, exprbuf);
1036         return 0;
1037 }
1038
1039
1040 //
1041 // Generalized initialization directive
1042 // 
1043 // .init[.siz] [#count,] expression [.size] , ...
1044 // 
1045 // The size suffix on the ".init" directive becomes the default size of the
1046 // objects to deposit. If an item is preceeded with a sharp (immediate) sign
1047 // and an expression, it specifies a repeat count. The value to be deposited
1048 // may be followed by a size suffix, which overrides the default size.
1049 //
1050 int d_init(WORD def_siz)
1051 {
1052         VALUE count;
1053         VALUE eval;
1054         WORD eattr;
1055         WORD siz;
1056
1057         if ((scattr & SBSS) != 0)
1058                 return error(".init not permitted in BSS or ABS");
1059
1060         if (rgpu || rdsp)
1061                 return error("directive forbidden in gpu/dsp mode");
1062
1063         for(;;)
1064         {
1065                 // Get repeat count (defaults to 1)
1066                 if (*tok == '#')
1067                 {
1068                         ++tok;
1069
1070                         if (abs_expr(&count) != OK)
1071                                 return 0;
1072
1073                         if (*tok++ != ',')
1074                                 return error(comma_error);
1075                 }
1076                 else
1077                         count = 1;
1078
1079                 // Evaluate expression to deposit
1080                 if (expr(exprbuf, &eval, &eattr, NULL) < 0)
1081                         return 0;
1082
1083                 switch ((int)*tok++)
1084                 {                                 // Determine size of object to deposit
1085                 case DOTB: siz = SIZB; break;
1086                 case DOTW: siz = SIZB; break;
1087                 case DOTL: siz = SIZL; break;
1088                 default: 
1089                         siz = def_siz;
1090                         --tok;
1091                         break;
1092                 }
1093
1094                 dep_block(count, siz, eval, eattr, exprbuf);
1095
1096                 switch ((int)*tok)
1097                 {
1098                 case EOL:
1099                         return 0;
1100                 case ',':
1101                         ++tok;
1102                         continue;
1103                 default:
1104                         return error(comma_error);
1105                 }
1106         }
1107 }
1108
1109
1110 //
1111 // Deposit 'count' values of size 'siz' in the current (non-BSS) segment
1112 //
1113 int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf)
1114 {
1115         WORD tdb;
1116         WORD defined;
1117
1118         tdb = (WORD)(eattr & TDB);
1119         defined = (WORD)(eattr & DEFINED);
1120
1121         while (count--)
1122         {
1123                 if ((challoc - ch_size) < 4)
1124                         chcheck(4L);
1125
1126                 switch(siz)
1127                 {
1128                 case SIZB:
1129                         if (!defined)
1130                         {
1131                                 fixup(FU_BYTE | FU_SEXT, sloc, exprbuf);
1132                                 D_byte(0);
1133                         }
1134                         else
1135                         {
1136                                 if (tdb)
1137                                         return error("non-absolute byte value");
1138
1139                                 if (eval + 0x100 >= 0x200)
1140                                         return error(range_error);
1141
1142                                 D_byte(eval);
1143                         }
1144
1145                         break;
1146                 case SIZW:
1147                 case SIZN:
1148                         if (!defined)
1149                         {
1150                                 fixup(FU_WORD | FU_SEXT, sloc, exprbuf);
1151                                 D_word(0);
1152                         }
1153                         else
1154                         {
1155                                 if (tdb)
1156                                         rmark(cursect, sloc, tdb, MWORD, NULL);
1157
1158                                 if (eval + 0x10000 >= 0x20000)
1159                                         return error(range_error);
1160
1161                                 // Deposit 68000 or 6502 (byte-reversed) word
1162                                 D_word(eval);
1163                         }
1164
1165                         break;
1166                 case SIZL:
1167                         if (!defined)
1168                         {
1169                                 fixup(FU_LONG, sloc, exprbuf);
1170                                 D_long(0);
1171                         }
1172                         else
1173                         {
1174                                 if (tdb)
1175                                         rmark(cursect, sloc, tdb, MLONG, NULL);
1176
1177                                 D_long(eval);
1178                         }
1179
1180                         break;
1181                 }
1182         }
1183
1184         return 0;
1185 }
1186
1187
1188 //
1189 // .comm symbol, size
1190 //
1191 int d_comm(void)
1192 {
1193         SYM * sym;
1194         char * p;
1195         VALUE eval;
1196
1197         if (*tok != SYMBOL)
1198                 return error("missing symbol");
1199
1200 //      p = (char *)tok[1];
1201         p = string[tok[1]];
1202         tok += 2;
1203
1204         if (*p == '.')                                                  // Cannot .comm a local symbol
1205                 return error(locgl_error);
1206
1207         if ((sym = lookup(p, LABEL, 0)) == NULL)
1208                 sym = NewSymbol(p, LABEL, 0);
1209         else
1210         {
1211                 if (sym->sattr & DEFINED)
1212                         return error(".comm symbol already defined");
1213         }
1214
1215         sym->sattr = GLOBAL | COMMON | BSS;
1216
1217         if (*tok++ != ',')
1218                 return error(comma_error);
1219
1220         if (abs_expr(&eval) != OK)                              // Parse size of common region
1221                 return 0;
1222
1223         sym->svalue = eval;                                             // Install common symbol's size
1224         at_eol();
1225         return 0;
1226 }
1227
1228
1229 //
1230 // .list - Turn listing on
1231 //
1232 int d_list(void)
1233 {
1234         if (list_flag)
1235                 listing++;
1236
1237         return 0;
1238 }
1239
1240
1241 //
1242 // .nlist - Turn listing off
1243 //
1244 int d_nlist(void)
1245 {
1246         if (list_flag)
1247                 listing--;
1248
1249         return 0;
1250 }
1251
1252
1253 //
1254 // .68000 - Back to 68000 TEXT segment
1255 //
1256 int d_68000(void)
1257 {
1258         rgpu = rdsp = 0;
1259         // Switching from gpu/dsp sections should reset any ORG'd Address
1260         orgactive = 0;                               
1261         orgwarning = 0;
1262         savsect();
1263         switchsect(TEXT);
1264         return 0;
1265 }
1266
1267
1268 //
1269 // .gpu - Switch to GPU Assembler
1270 //
1271 int d_gpu(void)
1272 {
1273         if ((cursect != TEXT) && (cursect != DATA))
1274         {
1275                 error(".gpu can only be used in the TEXT or DATA segments");
1276                 return ERROR;
1277         }
1278
1279         // If previous section was dsp or 68000 then we need to reset ORG'd Addresses
1280         if (!rgpu)
1281         {
1282                 orgactive = 0;
1283                 orgwarning = 0;
1284         }
1285
1286         rgpu = 1;                       // Set GPU assembly
1287         rdsp = 0;                       // Unset DSP assembly
1288         regbank = BANK_N;       // Set no default register bank
1289         return 0;
1290 }
1291
1292
1293 //
1294 // .dsp - Switch to DSP Assembler
1295 //
1296 int d_dsp(void)
1297 {
1298         if ((cursect != TEXT) && (cursect != DATA))
1299         {
1300                 error(".dsp can only be used in the TEXT or DATA segments");
1301                 return ERROR;
1302         }
1303
1304         // If previous section was gpu or 68000 then we need to reset ORG'd Addresses
1305         if (!rdsp)
1306         {
1307                 orgactive = 0;
1308                 orgwarning = 0;
1309         }
1310
1311         rdsp = 1;                       // Set DSP assembly
1312         rgpu = 0;                       // Unset GPU assembly
1313         regbank = BANK_N;       // Set no default register bank
1314         return 0;
1315 }
1316
1317
1318 //
1319 // .cargs [#offset], symbol[.size], ...
1320 // 
1321 // Lists of registers may also be mentioned; they just take up space. Good for
1322 // "documentation" purposes:
1323 // 
1324 // .cargs a6, .arg1, .arg2, .arg3...
1325 // 
1326 // Symbols thus created are ABS and EQUATED.
1327 //
1328 int d_cargs(void)
1329 {
1330         VALUE eval = 4;         // Default to 4 if no offset specified (to account for
1331                                                 // return address)
1332         WORD rlist;
1333         SYM * symbol;
1334         char * p;
1335         int env;
1336         int i;
1337
1338         if (rgpu || rdsp)
1339                 return error("directive forbidden in gpu/dsp mode");
1340
1341         if (*tok == '#')
1342         {
1343                 tok++;
1344
1345                 if (abs_expr(&eval) != OK)
1346                         return 0;
1347
1348                 // Eat the comma, if it's there
1349                 if (*tok == ',')
1350                         tok++;
1351         }
1352
1353         for(;;)
1354         {
1355                 if (*tok == SYMBOL)
1356                 {
1357 //                      p = (char *)tok[1];
1358                         p = string[tok[1]];
1359
1360 #if 0
1361                         if (*p == '.')
1362                                 env = curenv;                   // Label is local
1363                         else
1364                                 env = 0;                                // Label is global
1365 #else
1366                         // Set env to either local (dot prefixed) or global scope
1367                         env = (*p == '.' ? curenv : 0);
1368 #endif
1369                         symbol = lookup(p, LABEL, env);
1370
1371                         if (symbol == NULL)
1372                         {
1373                                 symbol = NewSymbol(p, LABEL, env);
1374                                 symbol->sattr = 0;
1375                         }
1376                         else if (symbol->sattr & DEFINED)
1377                                 return errors("multiply-defined label '%s'", p);
1378
1379                         // Put symbol in "order of definition" list
1380                         if (!(symbol->sattr & SDECLLIST))
1381                                 sym_decl(symbol);
1382
1383                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1384                         symbol->svalue = eval;
1385                         tok += 2;
1386
1387                         // What this does is eat any dot suffixes attached to a symbol. If
1388                         // it's a .L, it adds 4 to eval; if it's .W or .B, it adds 2. If
1389                         // there is no dot suffix, it assumes a size of 2.
1390                         switch ((int)*tok)
1391                         {
1392                         case DOTL:
1393                                 eval += 2;
1394                         case DOTB:
1395                         case DOTW:
1396                                 tok++;
1397                         }
1398
1399                         eval += 2;
1400                 }
1401                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1402                 {
1403                         if (reglist(&rlist) < 0)
1404                                 return 0;
1405
1406 //                      for(i=0; i++<16; rlist>>=1)
1407                         for(i=0; i<16; i++, rlist>>=1)
1408                         {
1409                                 if (rlist & 1)
1410                                         eval += 4;
1411                         }
1412                 }
1413                 else
1414                 {
1415                         switch ((int)*tok)
1416                         {
1417                         case KW_USP:
1418                         case KW_SSP:
1419                         case KW_PC:
1420                                 eval += 2;
1421                                 // FALLTHROUGH
1422                         case KW_SR:
1423                         case KW_CCR:
1424                                 eval += 2;
1425                                 tok++;
1426                                 break;
1427                         case EOL:
1428                                 return 0;
1429                         default:
1430                                 return error(".cargs syntax");
1431                         }
1432                 }
1433
1434                 // Eat commas in between each argument, if they exist
1435                 if (*tok == ',')
1436                         tok++;
1437         }
1438 }
1439
1440
1441 //
1442 // .cstruct [#offset], symbol[.size], ...
1443 // 
1444 // Lists of registers may also be mentioned; they just take up space. Good for
1445 // "documentation" purposes:
1446 // 
1447 // .cstruct a6, .arg1, .arg2, .arg3...
1448 // 
1449 // Symbols thus created are ABS and EQUATED. Note that this is for
1450 // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for
1451 // the suggestion.
1452 //
1453 int d_cstruct(void)
1454 {
1455         VALUE eval = 0;         // Default, if no offset specified, is zero
1456         WORD rlist;
1457         SYM * symbol;
1458         char * symbolName;
1459         int env;
1460         int i;
1461
1462         if (rgpu || rdsp)
1463                 return error("directive forbidden in gpu/dsp mode");
1464
1465         if (*tok == '#')
1466         {
1467                 tok++;
1468
1469                 if (abs_expr(&eval) != OK)
1470                         return 0;
1471
1472                 // Eat the comma, if it's there
1473                 if (*tok == ',')
1474                         tok++;
1475         }
1476
1477         for(;;)
1478         {
1479                 if (*tok == SYMBOL)
1480                 {
1481                         symbolName = string[tok[1]];
1482
1483                         // Set env to either local (dot prefixed) or global scope
1484                         env = (symbolName[0] == '.' ? curenv : 0);
1485                         symbol = lookup(symbolName, LABEL, env);
1486
1487                         // If the symbol wasn't found, then define it. Otherwise, throw an
1488                         // error.
1489                         if (symbol == NULL)
1490                         {
1491                                 symbol = NewSymbol(symbolName, LABEL, env);
1492                                 symbol->sattr = 0;
1493                         }
1494                         else if (symbol->sattr & DEFINED)
1495                                 return errors("multiply-defined label '%s'", symbolName);
1496
1497                         // Put symbol in "order of definition" list
1498                         if (!(symbol->sattr & SDECLLIST))
1499                                 sym_decl(symbol);
1500
1501                         tok += 2;
1502
1503                         // Adjust label start address if it's a word or a long, as a byte
1504                         // label might have left us on an odd address.
1505                         switch ((int)*tok)
1506                         {
1507                         case DOTW:
1508                         case DOTL:
1509                                 eval += eval & 0x01;
1510                         }
1511
1512                         symbol->sattr |= (ABS | DEFINED | EQUATED);
1513                         symbol->svalue = eval;
1514
1515                         // Check for dot suffixes and adjust space accordingly (longs and
1516                         // words on an odd boundary get bumped to the next word aligned
1517                         // address). If no suffix, then throw an error.
1518                         switch ((int)*tok)
1519                         {
1520                         case DOTL:
1521                                 eval += 4;
1522                                 break;
1523                         case DOTW:
1524                                 eval += 2;
1525                                 break;
1526                         case DOTB:
1527                                 eval += 1;
1528                                 break;
1529                         default:
1530                                 return error("Symbol missing dot suffix in .cstruct construct");
1531                         }
1532
1533                         tok++;
1534                 }
1535                 else if (*tok >= KW_D0 && *tok <= KW_A7)
1536                 {
1537                         if (reglist(&rlist) < 0)
1538                                 return 0;
1539
1540                         for(i=0; i<16; i++, rlist>>=1)
1541                         {
1542                                 if (rlist & 1)
1543                                         eval += 4;
1544                         }
1545                 }
1546                 else
1547                 {
1548                         switch ((int)*tok)
1549                         {
1550                         case KW_USP:
1551                         case KW_SSP:
1552                         case KW_PC:
1553                                 eval += 2;
1554                                 // FALLTHROUGH
1555                         case KW_SR:
1556                         case KW_CCR:
1557                                 eval += 2;
1558                                 tok++;
1559                                 break;
1560                         case EOL:
1561                                 return 0;
1562                         default:
1563                                 return error(".cstruct syntax");
1564                         }
1565                 }
1566
1567                 // Eat commas in between each argument, if they exist
1568                 if (*tok == ',')
1569                         tok++;
1570         }
1571 }
1572
1573
1574 //
1575 // Undefine a macro - .undefmac macname [, macname...]
1576 //
1577 int undmac1(char * p)
1578 {
1579         SYM * symbol = lookup(p, MACRO, 0);
1580
1581         // If the macro symbol exists, cause it to disappear
1582 //      if ((sy = lookup(p, MACRO, 0)) != NULL)
1583         if (symbol != NULL)
1584                 symbol->stype = (BYTE)SY_UNDEF;
1585
1586         return OK;
1587 }
1588
1589
1590 int d_undmac(void)
1591 {
1592         symlist(undmac1);
1593         return 0;
1594 }
1595