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