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