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