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