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