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