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