X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=direct.c;h=b2e67998e863a7a216e16b8b8b4f2bd8dd39599d;hp=0cee4b37640c331429b5f0c7c6134dc3ca34d91d;hb=60f204cb9e3905100da0d89f14bb40db764acd9e;hpb=e86444a037c470d010786006fbcaa7d6b56effdb diff --git a/direct.c b/direct.c index 0cee4b3..b2e6799 100644 --- a/direct.c +++ b/direct.c @@ -1,7 +1,7 @@ // // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // DIRECT.C - Directive Handling -// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -77,8 +77,8 @@ int (*dirtab[])() = { d_title, // 44 title d_subttl, // 45 subttl eject, // 46 eject - d_unimpl, // 47 error - d_unimpl, // 48 warn + d_error, // 47 error + d_warn, // 48 warn d_noclear, // 49 .noclear d_equrundef, // 50 .equrundef/.regundef d_ccundef, // 51 .ccundef @@ -87,9 +87,53 @@ int (*dirtab[])() = { d_jpad, // 54 .jpad (deprecated) d_nojpad, // 55 .nojpad (deprecated) d_gpumain, // 56 .gpumain (deprecated) + d_prgflags, // 57 .prgflags + d_opt, // 58 .opt }; +// +// .error - Abort compilation, printing an error message +// +int d_error(char *str) +{ + if (*tok == EOL) + return error("error directive encountered - aborting assembling"); + else + { + switch(*tok) + { + case STRING: + return error(string[tok[1]]); + break; + default: + return error("error directive encountered - aborting assembling"); + } + } +} + + +// +// .warn - Just display a warning on screen +// +int d_warn(char *str) +{ + if (*tok == EOL) + return warn("WARNING WARNING WARNING"); + else + { + switch(*tok) + { + case STRING: + return warn(string[tok[1]]); + break; + default: + return warn("WARNING WARNING WARNING"); + } + } +} + + // // .org - Set origin // @@ -97,7 +141,7 @@ int d_org(void) { VALUE address; - if (!rgpu && !rdsp) + if (!rgpu && !rdsp) return error(".org permitted only in gpu/dsp section"); orgaddr = 0; @@ -140,7 +184,7 @@ int d_print(void) sprintf(prntstr, "%s", string[tok[1]]); printf("%s", prntstr); - if (list_fd) + if (list_fd) unused = write(list_fd, prntstr, (LONG)strlen(prntstr)); tok += 2; @@ -178,9 +222,9 @@ int d_print(void) { switch(outtype) { - case 0: strcpy(format, "%X"); break; - case 1: strcpy(format, "%d" ); break; - case 2: strcpy(format, "%u" ); break; + case 0: strcpy(format, "%X"); break; + case 1: strcpy(format, "%d" ); break; + case 2: strcpy(format, "%u" ); break; } if (wordlong) @@ -190,7 +234,7 @@ int d_print(void) printf("%s", prntstr); - if (list_fd) + if (list_fd) unused = write(list_fd, prntstr, (LONG)strlen(prntstr)); formatting = 0; @@ -297,7 +341,7 @@ int d_noclear(void) } -// +// // Include binary file // int d_incbin(void) @@ -306,6 +350,8 @@ int d_incbin(void) int bytes = 0; long pos, size, bytesRead; char msg[256]; + char buf1[256]; + int i; // Check to see if we're in BSS, and, if so, throw an error if (scattr & SBSS) @@ -320,12 +366,30 @@ int d_incbin(void) return ERROR; } - if ((fd = open(string[tok[1]], _OPEN_INC)) < 0) + // Attempt to open the include file in the current directory, then (if that + // failed) try list of include files passed in the enviroment string or by + // the "-d" option. + if ((fd = open(string[tok[1]], _OPEN_INC)) < 0) { - errors("cannot open include binary file (%s)", string[tok[1]]); - return ERROR; + for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++) + { + fd = strlen(buf1); + + // Append path char if necessary + if (fd > 0 && buf1[fd - 1] != SLASHCHAR) + strcat(buf1, SLASHSTRING); + + strcat(buf1, string[tok[1]]); + + if ((fd = open(buf1, _OPEN_INC)) >= 0) + goto allright; + } + + return errors("cannot open: \"%s\"", string[tok[1]]); } +allright: + size = lseek(fd, 0L, SEEK_END); pos = lseek(fd, 0L, SEEK_SET); chcheck(size); @@ -356,7 +420,7 @@ int d_incbin(void) } -// +// // Set RISC register banks // int d_regbank0(void) @@ -404,7 +468,7 @@ static inline void SkipBytes(unsigned bytesToSkip) int d_even(void) { unsigned skip = (rgpu || rdsp ? orgaddr : sloc) & 0x01; - + if (skip) { if ((scattr & SBSS) == 0) @@ -517,7 +581,7 @@ int d_unimpl(void) } -// +// // Return absolute (not TDB) and defined expression or return an error // int abs_expr(VALUE * a_eval) @@ -578,7 +642,7 @@ int d_include(void) char buf[128]; char buf1[128]; - if (*tok == STRING) // Leave strings ALONE + if (*tok == STRING) // Leave strings ALONE fn = string[*++tok]; else if (*tok == SYMBOL) // Try to append ".s" to symbols { @@ -586,7 +650,7 @@ int d_include(void) fext(buf, ".s", 0); fn = &buf[0]; } - else // Punt if no STRING or SYMBOL + else // Punt if no STRING or SYMBOL return error("missing filename"); // Make sure the user didn't try anything like: @@ -596,14 +660,15 @@ int d_include(void) // Attempt to open the include file in the current directory, then (if that // failed) try list of include files passed in the enviroment string or by - // the "-d" option. + // the "-i" option. if ((j = open(fn, 0)) < 0) { for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++) { j = strlen(buf1); - if (j > 0 && buf1[j - 1] != SLASHCHAR) // Append path char if necessary + // Append path char if necessary + if (j > 0 && buf1[j - 1] != SLASHCHAR) strcat(buf1, SLASHSTRING); strcat(buf1, fn); @@ -663,7 +728,7 @@ int globl1(char * p) sy->sattr = GLOBAL; //printf("glob1: Making global symbol: attr=%04X, eattr=%08X, %s\n", sy->sattr, sy->sattre, sy->sname); } - else + else sy->sattr |= GLOBAL; return OK; @@ -677,6 +742,27 @@ int d_globl(void) } +// +// .prgflags expression +// +int d_prgflags(void) +{ + VALUE eval; + + if (*tok == EOL) + return error("PRGFLAGS requires value"); + else if (abs_expr(&eval) == OK) + { + PRGFLAGS=eval; + return 0; + } + else + { + return error("PRGFLAGS requires value"); + } +} + + // // .abs [expression] // @@ -750,8 +836,7 @@ int d_bss(void) // int d_ds(WORD siz) { -if (verb_flag) - printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc); + DEBUG { printf("Directive: .ds.[size] = %u, sloc = $%X\n", siz, sloc); } VALUE eval; @@ -762,21 +847,26 @@ if (verb_flag) if (as68_flag == 0 && (scattr & SBSS) == 0) return error(".ds permitted only in BSS"); - if (siz != SIZB && (sloc & 1)) // Automatic .even + if ((siz != SIZB) && (sloc & 1)) // Automatic .even auto_even(); if (abs_expr(&eval) != OK) return 0; + // Check to see if the value being passed in is negative (who the hell does + // that?--nobody does; it's the code gremlins, or rum, that does it) + if (eval < 0) + return error("negative sizes not allowed"); + // In non-TDB section (BSS, ABS and M6502) just advance the location // counter appropriately. In TDB sections, deposit (possibly large) chunks - //of zeroed memory.... + // of zeroed memory.... if (scattr & SBSS) { listvalue(eval); eval *= siz; sloc += eval; - just_bss = 1; // No data deposited (8-bit CPU mode) + just_bss = 1; // No data deposited (8-bit CPU mode) } else { @@ -789,17 +879,13 @@ if (verb_flag) // -// dc.b, dc.w / dc, dc.l +// dc.b, dc.w / dc, dc.l, dc.i // int d_dc(WORD siz) { WORD eattr; VALUE eval; - WORD tdb; - WORD defined; - LONG i; - char * p; - int movei = 0; // movei flag for dc.i + uint8_t * p; if ((scattr & SBSS) != 0) return error("illegal initialization of section"); @@ -815,24 +901,26 @@ int d_dc(WORD siz) || (rdsp && (orgaddr >= 0xF1B000) && (orgaddr <= 0xF1CFFFF)))) warn("depositing LONGs on a non-long address in local RAM"); - for(;; ++tok) + for(;; tok++) { // dc.b 'string' [,] ... if (siz == SIZB && *tok == STRING && (tok[2] == ',' || tok[2] == EOL)) { - i = strlen(string[tok[1]]); + uint32_t i = strlen(string[tok[1]]); - if ((challoc - ch_size) < i) + if ((challoc - ch_size) < i) chcheck(i); - for(p=string[tok[1]]; *p!=EOS; ++p) + for(p=string[tok[1]]; *p!=EOS; p++) D_byte(*p); tok += 2; goto comma; } - if (*tok == 'I') + int movei = 0; // MOVEI flag for dc.i + + if (*tok == DOTI) { movei = 1; tok++; @@ -840,11 +928,13 @@ int d_dc(WORD siz) } // dc.x - if (expr(exprbuf, &eval, &eattr, NULL) != OK) + SYM * esym = 0; + + if (expr(exprbuf, &eval, &eattr, &esym) != OK) return 0; - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); + uint16_t tdb = eattr & TDB; + uint16_t defined = eattr & DEFINED; if ((challoc - ch_size) < 4) chcheck(4); @@ -859,15 +949,15 @@ int d_dc(WORD siz) } else { - if (tdb) - return error("non-absolute byte value"); - if (eval + 0x100 >= 0x200) { sprintf(buffer, "%s (value = $%X)", range_error, eval); return error(buffer); } + if (tdb) + return error("non-absolute byte value"); + D_byte(eval); } @@ -881,13 +971,13 @@ int d_dc(WORD siz) } else { - if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); - if (eval + 0x10000 >= 0x20000) return error(range_error); - // Deposit 68000 or 6502 (byte-reversed) word + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); + + // Deposit 68000 or 6502 (byte-reversed) word D_word(eval); } @@ -905,16 +995,16 @@ int d_dc(WORD siz) else { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); - if (movei) - eval = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); + if (movei) + eval = WORDSWAP32(eval); D_long(eval); } break; } - + comma: if (*tok != ',') break; @@ -933,6 +1023,8 @@ int d_dcb(WORD siz) VALUE evalc, eval; WORD eattr; + DEBUG { printf("dcb: section is %s%s%s (scattr=$%X)\n", (cursect & TEXT ? "TEXT" : ""), (cursect & DATA ? " DATA" : ""), (cursect & BSS ? "BSS" : ""), scattr); } + if ((scattr & SBSS) != 0) return error("illegal initialization of section"); @@ -955,9 +1047,9 @@ int d_dcb(WORD siz) // // Generalized initialization directive -// +// // .init[.siz] [#count,] expression [.size] , ... -// +// // The size suffix on the ".init" directive becomes the default size of the // objects to deposit. If an item is preceeded with a sharp (immediate) sign // and an expression, it specifies a repeat count. The value to be deposited @@ -1001,9 +1093,9 @@ int d_init(WORD def_siz) case DOTB: siz = SIZB; break; case DOTW: siz = SIZB; break; case DOTL: siz = SIZL; break; - default: + default: siz = def_siz; - --tok; + tok--; break; } @@ -1014,7 +1106,7 @@ int d_init(WORD def_siz) case EOL: return 0; case ',': - ++tok; + tok++; continue; default: return error(comma_error); @@ -1069,7 +1161,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) else { if (tdb) - rmark(cursect, sloc, tdb, MWORD, NULL); + MarkRelocatable(cursect, sloc, tdb, MWORD, NULL); if (eval + 0x10000 >= 0x20000) return error(range_error); @@ -1088,7 +1180,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) else { if (tdb) - rmark(cursect, sloc, tdb, MLONG, NULL); + MarkRelocatable(cursect, sloc, tdb, MLONG, NULL); D_long(eval); } @@ -1172,7 +1264,7 @@ int d_68000(void) { rgpu = rdsp = 0; // Switching from gpu/dsp sections should reset any ORG'd Address - orgactive = 0; + orgactive = 0; orgwarning = 0; SaveSection(); SwitchSection(TEXT); @@ -1234,12 +1326,12 @@ int d_dsp(void) // // .cargs [#offset], symbol[.size], ... -// +// // Lists of registers may also be mentioned; they just take up space. Good for // "documentation" purposes: -// +// // .cargs a6, .arg1, .arg2, .arg3... -// +// // Symbols thus created are ABS and EQUATED. // int d_cargs(void) @@ -1347,12 +1439,12 @@ int d_cargs(void) // // .cstruct [#offset], symbol[.size], ... -// +// // Lists of registers may also be mentioned; they just take up space. Good for // "documentation" purposes: -// +// // .cstruct a6, .arg1, .arg2, .arg3... -// +// // Symbols thus created are ABS and EQUATED. Note that this is for // compatibility with VBCC and the Remover's library. Thanks to GroovyBee for // the suggestion. @@ -1485,7 +1577,6 @@ int undmac1(char * p) SYM * symbol = lookup(p, MACRO, 0); // If the macro symbol exists, cause it to disappear -// if ((sy = lookup(p, MACRO, 0)) != NULL) if (symbol != NULL) symbol->stype = (BYTE)SY_UNDEF; @@ -1519,3 +1610,30 @@ int d_gpumain(void) return error("What the hell? Do you think we adhere to the Goof standard?"); } + +// +// .opt - turn a specific (or all) optimisation on or off +// +int d_opt(void) +{ + while (*tok != EOL) + { + if (*tok == STRING) + { + tok++; + char * tmpstr = string[*tok++]; + + if (ParseOptimization(tmpstr) != OK) + { + char temperr[256]; + sprintf(temperr, "unknown optimization flag '%s'", tmpstr); + return error(temperr); + } + } + else + return error(".opt directive needs every switch enclosed inside quotation marks"); + } + + return OK; +} +