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