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
24 TOKEN exprbuf[128]; // Expression buffer
26 // Directive handler table
42 d_undmac, // 14 undefmac
49 d_incbin, // 21 .incbin //load
50 d_unimpl, // 22 disable
51 d_unimpl, // 23 enable
53 d_regbank0, // 25 .regbank0
54 d_regbank1, // 26 .regbank1
56 d_assert, // 28 assert
58 d_unimpl, // 30* endif
61 d_include, // 33 include
63 d_unimpl, // 35* macro
70 d_dphrase, // 42 struct
73 d_subttl, // 45 subttl
77 d_noclear, // 49 .noclear
78 d_equrundef, // 50 .equrundef/.regundef
79 d_ccundef, // 51 .ccundef
81 d_gpumain, // 53 .gpumain
83 d_nojpad, // 55 .nojpad
88 // --- .org - Set origin ---------------------------------------------------------------------------
97 // --- .org - Set origin ---------------------------------------------------------------------------
104 return(error(".org permitted only in gpu/dsp section"));
108 if(abs_expr(&address) == ERROR) {
109 error("cannot determine org'd address");
120 // --- NOP Padding Directive -----------------------------------------------------------------------
134 // --- Print Directive -----------------------------------------------------------------------------
138 char prntstr[LNSIZ]; // String for PRINT directive
139 char format[LNSIZ]; // Format for PRINT directive
140 int formatting = 0; // Formatting on/off
141 int wordlong = 0; // WORD = 0, LONG = 1
142 int outtype = 0; // 0:hex, 1:decimal, 2:unsigned
144 VALUE eval; // Expression value
145 WORD eattr; // Expression attributes
146 SYM *esym; // External symbol involved in expr.
147 TOKEN r_expr[EXPRSIZE];
152 sprintf(prntstr, "%s", (char*)tok[1]);
153 printf("%s", prntstr);
155 write(list_fd, prntstr, (LONG)strlen(prntstr));
160 if(tok[1] != SYMBOL) goto token_err;
161 strcpy(prntstr, (char*)tok[2]);
163 case 'l': case 'L': wordlong = 1; break;
164 case 'w': case 'W': wordlong = 0; break;
165 case 'x': case 'X': outtype = 0; break;
166 case 'd': case 'D': outtype = 1; break;
167 case 'u': case 'U': outtype = 2; break;
169 error("unknown print format flag");
178 if(expr(r_expr, &eval, &eattr, &esym) != OK)
182 case 0: strcpy(format, "%X"); break;
183 case 1: strcpy(format, "%d" ); break;
184 case 2: strcpy(format, "%u" ); break;
186 if(wordlong) sprintf(prntstr, format, eval);
187 else sprintf(prntstr, format, eval & 0xFFFF);
188 printf("%s", prntstr);
190 write(list_fd, prntstr, (LONG)strlen(prntstr));
205 error("illegal print token");
210 // --- Undefine an Equated Condition Code ----------------------------------------------------------
213 int d_ccundef(void) {
216 if(!rgpu && !rdsp) { // Check that we are in a RISC section
217 error(".ccundef must be defined in .gpu/.dsp section");
224 ccname = lookup((char *)tok[1], LABEL, 0);
225 if(!ccname || !(ccname->sattre & EQUATEDCC)) { // Make sure symbol is a valid ccdef
226 error("invalid equated condition name specified");
230 ccname->sattre |= UNDEF_CC;
236 // --- Undefine an Equated Register ----------------------------------------------------------------
239 int d_equrundef(void) {
242 if(!rgpu && !rdsp) { // Check that we are in a RISC section
243 error(".equrundef/.regundef must be defined in .gpu/.dsp section");
248 if(*tok == ',') tok++; // Skip preceeding or seperating commas
250 if(*tok != SYMBOL) { // Check we are dealing with a symbol
255 regname = lookup((char *)tok[1], LABEL, 0); // Lookup and undef if equated register
256 if(regname && (regname->sattre & EQUATEDREG))
257 regname->sattre |= UNDEF_EQUR;
259 tok += 2; // Skip over symbol token and address
266 // --- Do Not Allow the Use of the CLR.L Opcode ----------------------------------------------------
269 int d_noclear(void) {
274 // --- Include Binary File -------------------------------------------------------------------------
288 if((j = open((char *)tok[1], _OPEN_INC)) >= 0) {
289 size = lseek(j, 0L, SEEK_END);
291 pos = lseek(j, 0L, SEEK_SET);
293 for(i = 0; i < size; i++) {
295 bytes = read(j, &buf, 1);
300 errors("cannot open include binary file (%s)", (char*)tok[1]);
309 // --- Set RISC Register Banks ---------------------------------------------------------------------
312 int d_regbank0(void) {
313 regbank = BANK_0; // Set active register bank zero
317 int d_regbank1(void) {
318 regbank = BANK_1; // Set active register bank one
323 // --- Adjust Location to an EVEN Value ------------------------------------------------------------
328 if((scattr & SBSS) == 0) {
340 // --- Adjust Location to an LONG Value ------------------------------------------------------------
347 i = sloc & ~(val - 1);
348 if(i != sloc) val = val - (sloc - i);
352 if((scattr & SBSS) == 0) {
354 for(i = 0; i < val; i++)
365 // --- Adjust Location to an PHRASE Value ----------------------------------------------------------
372 i = sloc & ~(val - 1);
373 if(i != sloc) val = val - (sloc - i);
377 if((scattr & SBSS) == 0) {
379 for(i = 0; i < val; i++)
390 // --- Adjust Location to an DPHRASE Value ---------------------------------------------------------
393 int d_dphrase(void) {
397 i = sloc & ~(val - 1);
398 if(i != sloc) val = val - (sloc - i);
402 if((scattr & SBSS) == 0) {
404 for(i = 0; i < val; i++)
415 // --- Adjust Location to an QPHRASE Value ---------------------------------------------------------
418 int d_qphrase(void) {
422 i = sloc & ~(val - 1);
423 if(i != sloc) val = val - (sloc - i);
427 if((scattr & SBSS) == 0) {
430 for(i = 0; i < val; i++)
441 // -------------------------------------------------------------------------------------------------
442 // Do auto-even. This must be called ONLY if 'sloc' is odd.
444 // This is made hairy because, if there was a label on the line, we also have to adjust its value.
445 // This won't work with more than one label on the line, which is OK since multiple labels are only
446 // allowed in AS68 kludge mode, and the C compiler is VERY paranoid and uses ".even" whenever it can
447 // -------------------------------------------------------------------------------------------------
450 void auto_even(void) {
452 ++sloc; // Bump BSS section
454 D_byte(0) // Deposit 0.b in non-BSS
457 if(lab_sym != NULL) // Bump label if we have to
462 // --- Unimplemened Directive Error ----------------------------------------------------------------
466 return(error("unimplemented directive"));
470 // --- Return absolute (not TDB) and defined expression or return an error -------------------------
473 int abs_expr(VALUE *a_eval) {
476 if(expr(exprbuf, a_eval, &eattr, NULL) < 0)
478 if(!(eattr & DEFINED))
479 return(error(undef_error));
481 return(error(rel_error));
487 // --- Hand symbols in a symbol-list to a function (kind of like mapcar...) ------------------------
490 int symlist(int(*func)()) {
491 char *em = "symbol list syntax";
494 if(*tok != SYMBOL) return(error(em));
495 if((*func)(tok[1]) != OK) break;
497 if(*tok == EOL) break;
498 if(*tok != ',') return(error(em));
506 // --- .include "filename" -------------------------------------------------------------------------
509 int d_include(void) {
516 if(*tok == STRING) // Leave strings ALONE
518 else if(*tok == SYMBOL) { // Try to append ".s" to symbols
519 strcpy(buf, (char *)*++tok);
522 } else // Punt if no STRING or SYMBOL
523 return(error("missing filename"));
525 // Make sure the user didn't try anything like:
526 // .include equates.s
527 if(*++tok != EOL) return(error("extra stuff after filename -- enclose it in quotes"));
529 // Attempt to open the include file in the current directory, then (if that failed) try list
530 // of include files passed in the enviroment string or by the "-d" option.
531 if((j = open(fn, 0)) < 0) {
532 for(i = 0; nthpath("RMACPATH", i, buf1) != 0; ++i) {
534 if(j > 0 && buf1[j-1] != SLASHCHAR) // Append path char if necessary
535 strcat(buf1, SLASHSTRING);
537 if((j = open(buf1, 0)) >= 0)
541 return(errors("cannot open: \"%s\"", fn));
551 // --- .assert expression [, expression...] --------------------------------------------------------
558 for(; expr(exprbuf, &eval, &eattr, NULL) == OK; ++tok) {
559 if(!(eattr & DEFINED))
560 return(error("forward or undefined .assert"));
562 return(error("assert failure"));
571 // --- .globl symbol [, symbol] <<<cannot make local symbols global>>> -----------------------------
574 int globl1(char *p) {
578 return(error("cannot .globl local symbol"));
579 if((sy = lookup(p, LABEL, 0)) == NULL) {
580 sy = newsym(p, LABEL, 0);
595 // --- .abs [expression] ---------------------------------------------------------------------------
605 if(abs_expr(&eval) != OK)
614 // --- Switch Segments -----------------------------------------------------------------------------
619 return(error("directive forbidden in gpu/dsp mode"));
621 if(cursect != TEXT) {
630 return(error("directive forbidden in gpu/dsp mode"));
632 if(cursect != DATA) {
641 return(error("directive forbidden in gpu/dsp mode"));
651 // --- .ds[.size] expression -----------------------------------------------------------------------
657 // This gets kind of stupid. This directive is disallowed in normal 68000 mode ("for your own
658 // good!"), but is permitted for 6502 and Alcyon-compatibility modes.
659 // For obvious reasons, no auto-even is done in 8-bit processor modes.
660 if(as68_flag == 0 && (scattr & SBSS) == 0)
661 return(error(".ds permitted only in BSS"));
663 if(siz != SIZB && (sloc & 1)) // Automatic .even
666 if(abs_expr(&eval) != OK) return(0);
668 // In non-TDB section (BSS, ABS and M6502) just advance the location counter appropriately.
669 // In TDB sections, deposit (possibly large) chunks of zeroed memory....
670 if((scattr & SBSS)) {
674 just_bss = 1; // No data deposited (8-bit CPU mode)
676 dep_block(eval, siz, (VALUE)0, (WORD)(DEFINED|ABS), NULL);
684 // --- dc.b, dc.w / dc, dc.l -----------------------------------------------------------------------
694 int movei = 0; // movei flag for dc.i
696 if((scattr & SBSS) != 0)
697 return(error("illegal initialization of section"));
699 if((siz != SIZB) && (sloc & 1))
703 // dc.b 'string' [,] ...
704 if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL)) {
705 i = strlen((const char*)tok[1]);
706 if((challoc - ch_size) < i)
708 for(p = (char *)tok[1]; *p != EOS; ++p)
721 if(expr(exprbuf, &eval, &eattr, NULL) != OK)
723 tdb = (WORD)(eattr & TDB);
724 defined = (WORD)(eattr & DEFINED);
725 if((challoc - ch_size) < 4)
731 fixup(FU_BYTE|FU_SEXT, sloc, exprbuf);
735 return(error("non-absolute byte value"));
736 if(eval + 0x100 >= 0x200)
737 return(error(range_error));
744 fixup(FU_WORD|FU_SEXT, sloc, exprbuf);
748 rmark(cursect, sloc, tdb, MWORD, NULL);
749 if(eval + 0x10000 >= 0x20000)
750 return(error(range_error));
751 // Deposit 68000 or 6502 (byte-reversed) word
758 fixup(FU_LONG|FU_MOVEI, sloc, exprbuf);
760 fixup(FU_LONG, sloc, exprbuf);
764 rmark(cursect, sloc, tdb, MLONG, NULL);
766 eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000);
783 // --- dcb[.siz] expr1,expr2 - Make 'expr1' copies of 'expr2' --------------------------------------
786 int d_dcb(WORD siz) {
790 if((scattr & SBSS) != 0)
791 return(error("illegal initialization of section"));
793 if(abs_expr(&evalc) != OK)
797 return(error("missing comma"));
799 if(expr(exprbuf, &eval, &eattr, NULL) < 0)
802 if((siz != SIZB) && (sloc & 1))
805 dep_block(evalc, siz, eval, eattr, exprbuf);
810 // -------------------------------------------------------------------------------------------------
811 // Generalized initialization directive
813 // .init[.siz] [#count,] expression [.size] , ...
815 // The size suffix on the ".init" directive becomes the default size of the objects to deposit.
816 // If an item is preceeded with a sharp (immediate) sign and an expression, it specifies a repeat
817 // count. The value to be deposited may be followed by a size suffix, which overrides the
819 // -------------------------------------------------------------------------------------------------
822 int d_init(WORD def_siz) {
828 if((scattr & SBSS) != 0)
829 return(error(".init not permitted in BSS or ABS"));
832 return(error("directive forbidden in gpu/dsp mode"));
835 // Get repeat count (defaults to 1)
838 if(abs_expr(&count) != OK)
841 return(error(comma_error));
845 // Evaluate expression to deposit
846 if(expr(exprbuf, &eval, &eattr, NULL) < 0)
849 switch((int)*tok++) { // Determine size of object to deposit
850 case DOTB: siz = SIZB; break;
851 case DOTW: siz = SIZB; break;
852 case DOTL: siz = SIZL; break;
859 dep_block(count, siz, eval, eattr, exprbuf);
868 return(error(comma_error));
874 // --- Deposit 'count' values of size 'siz' in the current (non-BSS) segment -----------------------
877 int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN *exprbuf) {
881 tdb = (WORD)(eattr & TDB);
882 defined = (WORD)(eattr & DEFINED);
885 if((challoc - ch_size) < 4)
891 fixup(FU_BYTE|FU_SEXT, sloc, exprbuf);
895 return(error("non-absolute byte value"));
896 if(eval + 0x100 >= 0x200)
897 return(error(range_error));
904 fixup(FU_WORD|FU_SEXT, sloc, exprbuf);
908 rmark(cursect, sloc, tdb, MWORD, NULL);
909 if(eval + 0x10000 >= 0x20000)
910 return(error(range_error));
912 // Deposit 68000 or 6502 (byte-reversed) word
918 fixup(FU_LONG, sloc, exprbuf);
922 rmark(cursect, sloc, tdb, MLONG, NULL);
932 // --- .comm symbol, size --------------------------------------------------------------------------
941 return(error("missing symbol"));
945 if(*p == '.') // Cannot .comm a local symbol
946 return(error(locgl_error));
948 if((sym = lookup(p, LABEL, 0)) == NULL)
949 sym = newsym(p, LABEL, 0);
951 if(sym->sattr & DEFINED)
952 return(error(".comm symbol already defined"));
955 sym->sattr = GLOBAL|COMMON|BSS;
957 return(error(comma_error));
959 if(abs_expr(&eval) != OK) // Parse size of common region
961 sym->svalue = eval; // Install common symbol's size
967 // --- .list - Turn listing on --------------------------------------------------------------------
977 // --- .nlist - Turn listing off -------------------------------------------------------------------
987 // --- .68000 - Back to 68000 TEXT segment ---------------------------------------------------------
993 // Switching from gpu/dsp sections should reset any ORG'd Address
1002 // --- .gpu - Switch to GPU Assembler --------------------------------------------------------------
1006 if((cursect != TEXT) && (cursect != DATA)) {
1007 error(".gpu can only be used in the TEXT or DATA segments");
1010 // If previous section was dsp or 68000 then we need to reset ORG'd Addresses
1015 rgpu = 1; // Set GPU assembly
1016 rdsp = 0; // Unset DSP assembly
1017 regbank = BANK_N; // Set no default register bank
1024 // --- GPU Main Code Directive ---------------------------------------------------------------------
1027 int d_gpumain(void) {
1028 if((cursect != TEXT) && (cursect != DATA)) {
1029 error(".gpumain can only be used in the TEXT or DATA segments");
1032 // If previous section was dsp or 68000 then we need to reset ORG'd Addresses
1037 rgpu = 1; // Set GPU assembly
1038 rdsp = 0; // Unset DSP assembly
1039 regbank = BANK_N; // Set no default register bank
1040 in_main = 1; // Enable main code execution rules
1046 // --- .dsp - Switch to DSP Assembler --------------------------------------------------------------
1050 if((cursect != TEXT) && (cursect != DATA)) {
1051 error(".dsp can only be used in the TEXT or DATA segments");
1054 // If previous section was gpu or 68000 then we need to reset ORG'd Addresses
1059 rdsp = 1; // Set DSP assembly
1060 rgpu = 0; // Unset GPU assembly
1061 regbank = BANK_N; // Set no default register bank
1068 // -------------------------------------------------------------------------------------------------
1069 // .cargs [#offset], symbol[.size], ...
1071 // Lists of registers may also be mentioned; they just take up space. Good for "documentation"
1074 // .cargs a6,.arg1, .arg2, .arg3...
1076 // The symbols are ABS and EQUATED.
1077 // -------------------------------------------------------------------------------------------------
1089 return(error("directive forbidden in gpu/dsp mode"));
1093 if(abs_expr(&eval) != OK)
1095 if(*tok == ',') // Eat comma if it's there
1101 if(*tok == SYMBOL) {
1108 sy = lookup(p, LABEL, env);
1110 sy = newsym(p, LABEL, env);
1113 if(sy->sattr & DEFINED)
1114 return(errors("multiply-defined label '%s'", p));
1116 // Put symbol in "order of definition" list
1117 if(!(sy->sattr & SDECLLIST)) sym_decl(sy);
1119 sy->sattr |= ABS|DEFINED|EQUATED;
1132 if(*tok >= KW_D0 && *tok <= KW_A7) {
1133 if(reglist(&rlist) < 0)
1135 for(i = 0; i++ < 16; rlist >>= 1)
1153 return(error(".cargs syntax"));
1162 // --- Undefine a macro - .undefmac macname [, macname...] -----------------------------------------
1165 int undmac1(char *p) {
1168 // If the macro symbol exists, cause it to dissappear
1169 if((sy = lookup(p, MACRO, 0)) != NULL) sy->stype = (BYTE)SY_UNDEF;
1173 int d_undmac(void) {