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