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