X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=rmac.c;h=4772d203bd93d612f5e9e6a7121ae37e98fc9786;hp=3f021e7c495713f187d4193fd25a18bc5d191d7d;hb=HEAD;hpb=29fa5dcf504b966803063a1c2891f58f97126d04 diff --git a/rmac.c b/rmac.c index 3f021e7..17715f7 100644 --- a/rmac.c +++ b/rmac.c @@ -1,7 +1,7 @@ // -// RMAC - Reboot's Macro Assembler for all Atari computers +// RMAC - Renamed Macro Assembler for all Atari computers // RMAC.C - Main Application Code -// Copyright (C) 199x Landon Dyer, 2011-2019 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2022 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -29,10 +29,10 @@ int list_flag; // "-l" listing flag on command line int list_pag = 1; // Enable listing pagination by default int verb_flag; // Be verbose about what's going on int m6502; // 1, assembling 6502 code -int as68_flag; // as68 kludge mode int glob_flag; // Assume undefined symbols are global -int lsym_flag; // Include local symbols in object file -int sbra_flag; // Warn about possible short branches +int lsym_flag; // Include local symbols in object file (ALWAYS true) +int dsym_flag; // Gen debug syms (Requires obj_format = BSD) +int optim_warn_flag; // Warn about possible short branches int prg_flag; // !=0, produce .PRG executable (2=symbols) int prg_extend; // !=0, output extended .PRG symbols int legacy_flag; // Do stuff like insert code in RISC assembler @@ -44,18 +44,25 @@ int rgpu, rdsp; // Assembling Jaguar GPU or DSP code int robjproc; // Assembling Jaguar Object Processor code int dsp56001; // Assembling DSP 56001 code int list_fd; // File to write listing to -int regbank; // RISC register bank int segpadsize; // Segment padding size int endian; // Host processor endianess (0 = LE, 1 = BE) +int *regbase; // Points to current DFA register table (base) +int *regtab; // Points to current DFA register table (tab) +int *regcheck; // Points to current DFA register table (check) +int *regaccept; // Points to current DFA register table (accept) char * objfname; // Object filename pointer char * firstfname; // First source filename char * cmdlnexec; // Executable name, pointer to ARGV[0] -char * searchpath; // Search path for include files +char searchpatha[512] = { 0 }; // Buffer to hold searchpath when specified +char * searchpath = NULL; // Search path for include files char defname[] = "noname.o"; // Default output filename -int optim_flags[OPT_COUNT]; // Specific optimisations on/off matrix +int optim_flags[OPT_COUNT_ALL] = { 0 }; // Specific optimisations on/off matrix int activecpu = CPU_68000; // Active 68k CPU (68000 by default) int activefpu = FPU_NONE; // Active FPU (none by default) - +int org68k_active = 0; // .org switch for 68k (only with RAW output format) +uint32_t org68k_address; // .org for 68k +int correctMathRules; // 1, use C operator precedence in expressions +uint32_t used_architectures; // Bitmask that records exactly which architectures were used during assembly // // Convert a string to uppercase @@ -66,7 +73,6 @@ void strtoupper(char * s) *s++ &= 0xDF; } - // // Manipulate file extension. // @@ -99,6 +105,17 @@ char * fext(char * name, char * extension, int stripp) return name; } +static int is_sep(char c) +{ + const char *seps = PATH_SEPS; + + for (seps = PATH_SEPS; *seps; seps++) { + if (*seps == c) + return 1; + } + + return 0; +} // // Return 'item'nth element of semicolon-seperated pathnames specified in the @@ -118,13 +135,13 @@ int nthpath(char * env_var, int itemno, char * buf) return 0; while (itemno--) - while (*s != EOS && *s++ != ';') + while (*s != EOS && !is_sep(*s++)) ; if (*s == EOS) return 0; - while (*s != EOS && *s != ';') + while (*s != EOS && !is_sep(*s)) *buf++ = *s++; *buf++ = EOS; @@ -132,7 +149,6 @@ int nthpath(char * env_var, int itemno, char * buf) return 1; } - // // Display command line help // @@ -146,46 +162,43 @@ void DisplayHelp(void) " -dsymbol[=value] Define symbol (with optional value, default=0)\n" " -e[errorfile] Send error messages to file, not stdout\n" " -f[format] Output object file format\n" - " a: ALCYON (use this for ST)\n" + " a: ALCYON\n" " b: BSD (use this for Jaguar)\n" + " c: PRG (C64)\n" " e: ELF\n" " p: P56 (use this for DSP56001 only)\n" " l: LOD (use this for DSP56001 only)\n" " x: com/exe/xex (Atari 800)\n" + " r: absolute address\n" + " -g Output source level debug information (BSD object only)\n" " -i[path] Directory to search for include files\n" " -l[filename] Create an output listing file\n" " -l*[filename] Create an output listing file without pagination\n" " -m[cpu] Select default CPU. Available options:\n" - " 68000\n" - " 68020\n" - " 68030\n" - " 68040\n" - " 68060\n" - " 6502\n" - " tom\n" - " jerry\n" - " 56001\n" + " 68000, 68020, 68030, 68040, 68060, 6502, tom, jerry, 56001\n" " -n Don't do things behind your back in RISC assembler\n" " -o file Output file name\n" " +o[value] Turn a specific optimisation on\n" - " Available optimisation values and default settings:\n" - " o0: Absolute long adddresses to word (on)\n" - " o1: move.l #x,dn/an to moveq (on)\n" - " o2: Word branches to short (on)\n" - " o3: Outer displacement 0(an) to (an) (off)\n" - " o4: lea size(An),An to addq #size,An (off)\n" - " o5: Absolute long base displacement to word (off)\n" - " o6: Null branches to NOP (off)\n" - " o7: clr.l Dx to moveq #0,Dx (off)\n" - " o8: adda.w/l #x,Dy to addq.w/l #x,Dy (off)\n" - " o9: adda.w/l #x,Dy to lea x(Dy),Dy (off)\n" + " Available optimisation switches:\n" + " o0: Absolute long addresses to word\n" + " o1: move.l #x,dn/an to moveq\n" + " o2: Word branches to short\n" + " o3: Outer displacement 0(an) to (an)\n" + " o4: lea size(An),An to addq #size,An\n" + " o5: 68020+ Absolute long base/outer disp. to word\n" + " o6: Null branches to NOP\n" + " o7: clr.l Dx to moveq #0,Dx\n" + " o8: adda.w/l #x,Dy to addq.w/l #x,Dy\n" + " o9: adda.w/l #x,Ay to lea x(Dy),Ay\n" + " o10: 56001 Use short format for immediate values if possible\n" + " o11: 56001 Auto convert short addressing mode to long (default: on)\n" + " o30: Enforce PC relative (alternative name: op)\n" " ~o[value] Turn a specific optimisation off\n" " +oall Turn all optimisations on\n" " ~oall Turn all optimisations off\n" - " -p Create an ST .prg (without symbols)\n" - " -ps Create an ST .prg (with symbols)\n" - " -px Create an ST .prg (with exsymbols)\n" - " Forces -fa\n" + " -p Create an ST .prg (without symbols). Forces -fa\n" + " -ps Create an ST .prg (with symbols). Forces -fa\n" + " -px Create an ST .prg (with exsymbols). Forces -fa\n" " -r[size] Pad segments to boundary size specified\n" " w: word (2 bytes, default alignment)\n" " l: long (4 bytes)\n" @@ -198,6 +211,7 @@ void DisplayHelp(void) " -v Set verbose mode\n" " -x Turn on debugging mode\n" " -y[pagelen] Set page line length (default: 61)\n" + " -4 Use C style operator precedence\n" "\n", cmdlnexec); } @@ -212,12 +226,11 @@ void DisplayVersion(void) "| '__| '_ ` _ \\ / _` |/ __|\n" "| | | | | | | | (_| | (__ \n" "|_| |_| |_| |_|\\__,_|\\___|\n" - "\nReboot's Macro Assembler\n" - "Copyright (C) 199x Landon Dyer, 2011-2018 Reboot\n" + "\nRenamed Macro Assembler\n" + "Copyright (C) 199x Landon Dyer, 2011-2022 Reboot and Friends\n" "V%01i.%01i.%01i %s (%s)\n\n", MAJOR, MINOR, PATCH, __DATE__, PLATFORM); } - // // Parse optimisation options // @@ -225,36 +238,102 @@ int ParseOptimization(char * optstring) { int onoff = 0; - if (*optstring == '+') - onoff = 1; - else if (*optstring != '~') - return ERROR; - - if ((optstring[2] == 'a' || optstring[2] == 'A') - && (optstring[3] == 'l' || optstring[3] == 'L') - && (optstring[4] == 'l' || optstring[4] == 'L')) - { - memset(optim_flags, onoff, OPT_COUNT * sizeof(int)); - return OK; - } - else if (optstring[1] == 'o' || optstring[1] == 'O') // Turn on specific optimisation + while (*optstring) { - int opt_no = atoi(&optstring[2]); + if (*optstring == '+') + onoff = 1; + else if (*optstring != '~') + return ERROR; - if ((opt_no >= 0) && (opt_no < OPT_COUNT)) + if (optstring[2] == 0) + return error(".opt called with zero arguments"); + + if ((optstring[2] == 'a' || optstring[2] == 'A') + && (optstring[3] == 'l' || optstring[3] == 'L') + && (optstring[4] == 'l' || optstring[4] == 'L')) + { + memset(optim_flags, onoff, OPT_COUNT * sizeof(int)); + optstring += 5; + } + else if (optstring[1] == 'o' || optstring[1] == 'O') // Turn on specific optimisation { - optim_flags[opt_no] = onoff; - return OK; + if (optstring[2] == 'p' || optstring[2] == 'P') + { + optim_flags[OPT_PC_RELATIVE] = onoff; + optstring += 3; + } + else + { + int opt_no = atoi(&optstring[2]); + + if ((opt_no >= 0) && (opt_no < OPT_COUNT)) + { + optim_flags[opt_no] = onoff; + optstring += 3; + + // If opt_no is 2 digits then consume an extra character. + // Sounds a bit sleazy but we know we're not going to hit + // more than 100 optimisation switches so this should be + // fine. If we do hit that number then it'll probably be + // time to burn the whole codebase and start from scratch. + if (opt_no > 9) + optstring++; + } + else + return ERROR; + } } else + { return ERROR; + } + + if (*optstring == ',') + optstring++; + } + return OK; +} + +static void ProcessFile(int fd, char *fname) +{ + char *dbgname = fname; + + if (NULL == fname) + { + fname = defname; // Kludge first filename + dbgname = "(stdin)"; } - else + + // First file operations: + if (firstfname == NULL) { - return ERROR; + // Record first filename. + firstfname = fname; + + // Validate option compatibility + if (dsym_flag) + { + if (obj_format != BSD) + { + printf("-g: debug information only supported with BSD object file format\n"); + dsym_flag = 0; + errcnt++; + } + else + { + GenMainFileSym(dbgname); + } + } } + + include(fd, dbgname); + Assemble(); } +extern int reg68base[53]; +extern int reg68tab[222]; +extern int reg68check[222]; +extern int reg68accept[222]; // // Process command line arguments and do an assembly @@ -267,34 +346,40 @@ int Process(int argc, char ** argv) int fd; // File descriptor char fnbuf[FNSIZ]; // Filename buffer int i; // Iterator - - errcnt = 0; // Initialise error count - listing = 0; // Initialise listing level - list_flag = 0; // Initialise listing flag - verb_flag = perm_verb_flag; // Initialise verbose flag - as68_flag = 0; // Initialise as68 kludge mode - glob_flag = 0; // Initialise .globl flag - sbra_flag = 0; // Initialise short branch flag - debug = 0; // Initialise debug flag - searchpath = NULL; // Initialise search path - objfname = NULL; // Initialise object filename - list_fname = NULL; // Initialise listing filename - err_fname = NULL; // Initialise error filename - obj_format = BSD; // Initialise object format - firstfname = NULL; // Initialise first filename - err_fd = ERROUT; // Initialise error file descriptor - err_flag = 0; // Initialise error flag - rgpu = 0; // Initialise GPU assembly flag - rdsp = 0; // Initialise DSP assembly flag - robjproc = 0; // Initialise OP assembly flag + int current_path_index = 0; // Iterator for search paths + + errcnt = 0; // Initialize error count + listing = 0; // Initialize listing level + list_flag = 0; // Initialize listing flag + verb_flag = perm_verb_flag; // Initialize verbose flag + glob_flag = 0; // Initialize .globl flag + optim_warn_flag = 0; // Initialize short branch flag + debug = 0; // Initialize debug flag + objfname = NULL; // Initialize object filename + list_fname = NULL; // Initialize listing filename + err_fname = NULL; // Initialize error filename + obj_format = BSD; // Initialize object format + firstfname = NULL; // Initialize first filename + err_fd = ERROUT; // Initialize error file descriptor + err_flag = 0; // Initialize error flag + rgpu = 0; // Initialize GPU assembly flag + rdsp = 0; // Initialize DSP assembly flag + robjproc = 0; // Initialize OP assembly flag lsym_flag = 1; // Include local symbols in object file - regbank = BANK_N; // No RISC register bank specified + dsym_flag = 0; // No debug sym generation by default orgactive = 0; // Not in RISC org section orgwarning = 0; // No ORG warning issued - segpadsize = 2; // Initialise segment padding size + segpadsize = 2; // Initialize segment padding size + dsp_orgmap[0].start = 0; // Initialize 56001 org initial address + dsp_orgmap[0].memtype = ORG_P; // Initialize 56001 org start segment m6502 = 0; // 6502 mode off by default - - // Initialise modules + regbase = reg68base; // Initialise DFA register tables + regtab = reg68tab; // Idem + regcheck = reg68check; // Idem + regaccept = reg68accept; // Idem + correctMathRules = 0; // respect operator precedence + used_architectures = 0; // Initialise used architectures bitfield + // Initialize modules InitSymbolTable(); // Symbol table InitTokenizer(); // Tokenizer InitLineProcessor(); // Line processor @@ -312,6 +397,9 @@ int Process(int argc, char ** argv) { switch (argv[argno][1]) { + case '4': + correctMathRules = 1; + break; case 'd': // Define symbol case 'D': for(s=argv[argno]+2; *s!=EOS;) @@ -358,6 +446,10 @@ int Process(int argc, char ** argv) case 'B': obj_format = BSD; break; + case 'c': + case 'C': + obj_format = C64PRG; + break; case 'e': // -fe = ELF case 'E': obj_format = ELF; @@ -374,6 +466,10 @@ int Process(int argc, char ** argv) case 'X': obj_format = XEX; break; + case 'r': // -fr = Absolute address + case 'R': + obj_format = RAW; + break; default: printf("-f: unknown object format specified\n"); errcnt++; @@ -382,12 +478,38 @@ int Process(int argc, char ** argv) break; case 'g': // Debugging flag case 'G': - printf("Debugging flag (-g) not yet implemented\n"); + dsym_flag = 1; break; case 'i': // Set directory search path case 'I': - searchpath = argv[argno] + 2; + { + strcat(searchpatha, argv[argno] + 2); + strcat(searchpatha, ";"); + searchpath = searchpatha; + + // Check to see if include paths actually exist + char current_path[256]; + + for(i=current_path_index; nthpath("RMACPATH", i, current_path)!=0; i++) + { + if (strlen(current_path) > 0) + { + DIR * test = opendir(current_path); + + if (test == NULL) + { + printf("Invalid include path: %s\n", current_path); + errcnt++; + return errcnt; + } + + closedir(test); + } + } + + current_path_index = i - 1; break; + } case 'l': // Produce listing file case 'L': if (*(argv[argno] + 2) == '*') @@ -497,9 +619,9 @@ int Process(int argc, char ** argv) default: segpadsize = 2; break; // Effective autoeven(); } break; - case 's': // Warn about possible short branches + case 's': // Warn about possible short branches and applied optimisations case 'S': - sbra_flag = 1; + optim_warn_flag = 1; break; case 'u': // Make undefined symbols .globl case 'U': @@ -531,11 +653,7 @@ int Process(int argc, char ** argv) break; case EOS: // Input is stdin - if (firstfname == NULL) // Kludge first filename - firstfname = defname; - - include(0, "(stdin)"); - Assemble(); + ProcessFile(0, NULL); break; case 'h': // Display command line usage case 'H': @@ -570,10 +688,6 @@ int Process(int argc, char ** argv) } else { - // Record first filename. - if (firstfname == NULL) - firstfname = argv[argno]; - strcpy(fnbuf, argv[argno]); fext(fnbuf, ".s", 0); fd = open(fnbuf, 0); @@ -585,8 +699,7 @@ int Process(int argc, char ** argv) continue; } - include(fd, fnbuf); - Assemble(); + ProcessFile(fd, fnbuf); } } @@ -645,7 +758,9 @@ int Process(int argc, char ** argv) if (firstfname == NULL) firstfname = defname; - strcpy(fnbuf, firstfname); + // It's the size of fnbuf minus 5 because of the possible 4 char suffix + // + trailing null (added by fext()). + strncpy(fnbuf, firstfname, sizeof(fnbuf) - 5); fext(fnbuf, (prg_flag ? ".prg" : ".o"), 1); objfname = fnbuf; } @@ -695,7 +810,6 @@ int Process(int argc, char ** argv) return errcnt; } - // // Determine processor endianess // @@ -710,7 +824,6 @@ int GetEndianess(void) return 1; } - // // Application entry point // @@ -718,12 +831,7 @@ int main(int argc, char ** argv) { perm_verb_flag = 0; // Clobber "permanent" verbose flag legacy_flag = 1; // Default is legacy mode on (:-P) - - // Set legacy optimisation flags to on and everything else to off - memset(optim_flags, 0, OPT_COUNT * sizeof(int)); - optim_flags[OPT_ABS_SHORT] = - optim_flags[OPT_MOVEL_MOVEQ] = - optim_flags[OPT_BSR_BCC_S] = 1; + optim_flags[OPT_56K_SHORT] = 1; // This ensures compatibilty with Motorola's 56k assembler cmdlnexec = argv[0]; // Obtain executable name endian = GetEndianess(); // Get processor endianess @@ -737,4 +845,3 @@ int main(int argc, char ** argv) return 0; } -