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