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