X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fxa51%2Fxa_main.c;h=345ca7e4ec44498a524c0ff0e3430715f88149c7;hb=249f657e4e40a413e0875886670ac1958a72cdde;hp=f632f562ae3ae221da817447016cdee20e5bd315;hpb=d8b175c6e67ca49b13fd458cf77ff5dbf7eee97e;p=fw%2Fsdcc diff --git a/as/xa51/xa_main.c b/as/xa51/xa_main.c index f632f562..345ca7e4 100644 --- a/as/xa51/xa_main.c +++ b/as/xa51/xa_main.c @@ -17,22 +17,38 @@ /* adapted from the osu8asm project, 1995 */ /* http://www.pjrc.com/tech/osu8/index.html */ -#define printf(x...) fprintf(stderr,x) +/* + made "relocatable" by johan.knol@iduna.nl for sdcc + + This isn't a standalone assembler anymore. It's only purpose is to + create relocatable modules (that has to be processed with xa_link) + out of sdcc-generated .xa files +*/ + +#define D(x) x #include #include #include +#include -#include "xa_main.h" +#define printf(x...) fprintf(stderr,x) +#include "xa_main.h" +#include "xa_version.h" extern void yyrestart(FILE *new_file); -extern void hexout(int byte, int memory_location, int end); extern int yyparse(); +char modulename[PATH_MAX]; +char infilename[PATH_MAX]; +char outfilename[PATH_MAX]; +char listfilename[PATH_MAX]; +char symfilename[PATH_MAX]; + /* global variables */ -FILE *fhex, *fmem, *list_fp; +FILE *frel, *fmem, *list_fp, *sym_fp; extern FILE *yyin; extern char *yytext; extern char last_line_text[]; @@ -41,23 +57,28 @@ struct target *targ_list=NULL; int lineno=1; int p1=0, p2=0, p3=0; int expr_result, expr_ok, jump_dest, inst; -int opcode, operand; +int opcode; char symbol_name[1000]; struct area_struct area[NUM_AREAS]; -int current_area=AREA_CSEG; +int current_area=0; +char rel_line[2][132]; char *areaToString (int area) { switch (area) { case AREA_CSEG: return "CSEG"; case AREA_DSEG: return "DSEG"; - case AREA_OSEG: return "OSEG"; - case AREA_ISEG: return "ISEG"; + //case AREA_OSEG: return "OSEG"; + //case AREA_ISEG: return "ISEG"; case AREA_BSEG: return "BSEG"; case AREA_XSEG: return "XSEG"; case AREA_XISEG: return "XISEG"; case AREA_XINIT: return "XINIT"; + case AREA_GSINIT: return "GSINIT"; + //case AREA_GSFINAL: return "GSFINAL"; + //case AREA_HOME: return "HOME"; + //case AREA_SSEG: return "SSEG"; } return ("UNKNOW"); } @@ -74,7 +95,16 @@ struct symbol * build_sym_list(char *thename) { struct symbol *new, *p; -/* printf(" Symbol: %s Line: %d\n", thename, lineno); */ + if ((p=findSymbol(thename))) { + if (p->isdef) { + fprintf (stderr, "error: symbol %s already defined\n", thename); + exit (1); + } else { + return p; + } + } + + //printf(" Symbol: %s Line: %d\n", thename, lineno); new = (struct symbol *) malloc(sizeof(struct symbol)); new->name = (char *) malloc(strlen(thename)+1); strcpy(new->name, thename); @@ -85,6 +115,7 @@ struct symbol * build_sym_list(char *thename) new->isreg = 0; new->line_def = lineno - 1; new->area = current_area; + new->mode = 'X'; // start with an external new->next = NULL; if (sym_list == NULL) return (sym_list = new); p = sym_list; @@ -93,24 +124,35 @@ struct symbol * build_sym_list(char *thename) return (new); } -int assign_value(char *thename, int thevalue) -{ - struct symbol *p; +struct symbol *findSymbol (char *thename) { + struct symbol *p; + for (p=sym_list; p; p=p->next) { + if (strcasecmp(thename, p->name)==0) { + return p; + } + } + return NULL; +} - p = sym_list; - while (p != NULL) { - if (!(strcasecmp(thename, p->name))) { - p->value = thevalue; - p->isdef = 1; - return (0); - } - p = p->next; - } - fprintf(stderr, "Internal Error! Couldn't find symbol\n"); - exit(1); +int assign_value(char *thename, int thevalue, char mode) { + struct symbol *p; + + p = sym_list; + while (p != NULL) { + if (!(strcasecmp(thename, p->name))) { + p->area=current_area; + p->value = thevalue; + p->isdef = 1; + p->mode = mode; + return (0); + } + p = p->next; + } + fprintf(stderr, "Internal Error! Couldn't find symbol\n"); + exit(1); } -int mk_bit(char *thename) +int mk_bit(char *thename, int area) { struct symbol *p; @@ -118,6 +160,24 @@ int mk_bit(char *thename) while (p != NULL) { if (!(strcasecmp(thename, p->name))) { p->isbit = 1; + p->area = area; + return (0); + } + p = p->next; + } + fprintf(stderr, "Internal Error! Couldn't find symbol\n"); + exit(1); +} + +int mk_sfr(char *thename) +{ + struct symbol *p; + + p = sym_list; + while (p != NULL) { + if (!(strcasecmp(thename, p->name))) { + p->issfr = 1; + p->area = 0; return (0); } p = p->next; @@ -143,19 +203,36 @@ int mk_reg(char *thename) exit(1); } - +int mk_global(char *thename) +{ + struct symbol *p; + + p = sym_list; + while (p != NULL) { + if (!(strcasecmp(thename, p->name))) { + p->global = 1; + return (0); + } + p = p->next; + } + fprintf(stderr, "Internal Error! Couldn't find symbol\n"); + exit(1); +} int get_value(char *thename) { - struct symbol *p; - p = sym_list; - while (p != NULL) { - if (!(strcasecmp(thename, p->name))) - return (p->value); - p = p->next; - } - fprintf(stderr, "Internal Error! Couldn't find symbol value\n"); - exit(1); + struct symbol *p; + p = sym_list; + while (p != NULL) { + if (!(strcasecmp(thename, p->name))) { + if (p->mode=='=') + ;//return 0; + return (p->value); + } + p = p->next; + } + fprintf(stderr, "Internal Error! Couldn't find symbol value\n"); + exit(1); } @@ -200,12 +277,31 @@ void print_symbol_table() struct symbol *p; p = sym_list; while (p != NULL) { - printf("Sym in %-5s: %s\n", areaToString(p->area), p->name); - printf(" at: 0x%04X (%5d)", p->value, p->value); - printf(" Def:%s", p->isdef ? "Yes" : "No "); - printf(" Bit:%s", p->isbit ? "Yes" : "No "); - printf(" Target:%s", p->istarget ? "Yes" : "No "); - printf(" Line %d\n", p->line_def); +#if 0 + fprintf(sym_fp, "Sym in %-5s: %s\n", areaToString(p->area), p->name); + fprintf(sym_fp, " at: 0x%04X (%5d)", p->value, p->value); + fprintf(sym_fp, " Def:%s", p->isdef ? "Yes" : "No "); + fprintf(sym_fp, " Bit:%s", p->isbit ? "Yes" : "No "); + fprintf(sym_fp, " Target:%s", p->istarget ? "Yes" : "No "); + fprintf(sym_fp, " Line %d\n", p->line_def); +#else + if (p->issfr) { + fprintf (sym_fp, "%-7s", "SFR"); + } else if (p->isbit && !p->area) { + fprintf (sym_fp, "%-7s", "SBIT"); + } else if (p->mode=='=') { + fprintf (sym_fp,"ABS "); + } else if (!p->isdef) { + fprintf (sym_fp,"EXTRN "); + } else { + fprintf (sym_fp, "%-7s", areaToString(p->area)); + } + fprintf (sym_fp, " 0x%04x (%5d)", p->value, p->value); + fprintf (sym_fp, " %s", p->isdef ? "D" : "-"); + fprintf (sym_fp, "%s", p->isbit ? "B" : "-"); + fprintf (sym_fp, "%s", p->istarget ? "T" : "-"); + fprintf (sym_fp, " %s\n", p->name); +#endif p = p->next; } } @@ -214,20 +310,21 @@ void print_symbol_table() void check_redefine() { - struct symbol *p1, *p2; - p1 = sym_list; - while (p1 != NULL) { - p2 = p1->next; - while (p2 != NULL) { - if (!strcasecmp(p1->name, p2->name)) { - fprintf(stderr, "Error: symbol '%s' redefined on line %d", p1->name, p2->line_def); - fprintf(stderr, ", first defined on line %d\n", p1->line_def); - exit(1); - } - p2 = p2->next; - } - p1 = p1->next; - } + struct symbol *p1, *p2; + p1 = sym_list; + while (p1 != NULL) { + p2 = p1->next; + while (p2 != NULL) { + if (!strcasecmp(p1->name, p2->name)) { + fprintf(stderr, "Error: symbol '%s' redefined on line %d", + p1->name, p2->line_def); + fprintf(stderr, ", first defined on line %d\n", p1->line_def); + exit(1); + } + p2 = p2->next; + } + p1 = p1->next; + } } int is_target(char *thename) @@ -264,15 +361,38 @@ int is_reg(char *thename) } -int is_def(char *thename) +struct symbol *is_def(char *thename) { - struct symbol *p; - p = sym_list; - while (p != NULL) { - if (!strcasecmp(thename, p->name) && p->isdef) return(1); - p = p->next; - } - return (0); + struct symbol *p; + p = sym_list; + while (p != NULL) { + if (!strcasecmp(thename, p->name) && p->isdef) + return p; + p = p->next; + } + return NULL; +} + +struct symbol *is_ref(char *thename) { + struct symbol *p; + p = sym_list; + while (p != NULL) { + if (strcasecmp(thename, p->name)==0) + return p; + p = p->next; + } + return NULL; +} + +int is_abs(char *thename) { + struct symbol *p; + p = sym_list; + while (p != NULL) { + if (strcasecmp(thename, p->name)==0) + return p->mode == '='; + p = p->next; + } + return 0; } /* this routine is used to dump a group of bytes to the output */ @@ -282,31 +402,81 @@ int is_def(char *thename) /* though is it expected that the lexer has placed all the actual */ /* original text from the line in "last_line_text" */ -void out(int *byte_list, int num) -{ - int i, first=1; - - if (num > 0) fprintf(list_fp, "%06X: ", MEM_POS); - else fprintf(list_fp, "\t"); - - for (i=0; i 0) fprintf(list_fp, "%06X: ", MEM_POS); + else fprintf(list_fp, "\t"); + + if (last_area!=current_area) { + // emit area information + if (area[current_area].size) { + fprintf (frel, "A %s size %d flags 0\n", + areaToString(current_area), + area[current_area].size); + if (!area[current_area].defsEmitted) { + for (p=sym_list; p; p=p->next) { + if (p->global && p->isdef && p->area==current_area) { + // skip temp labels + if (p->name[strlen(p->name)-1]!='$') { + if (p->mode=='=') { + fprintf (frel, "S %s Abs%04x\n", p->name, p->value); + } else { + fprintf (frel, "S %s Def%04x\n", p->name, p->value); + } + } + } } - if (first) { - if (num < 3) fprintf(list_fp, "\t"); - fprintf(list_fp, "\t%s\n", last_line_text); - } else { - if (num % 4) fprintf(list_fp, "\n"); + area[current_area].defsEmitted=1; + } + } + last_area=current_area; + } + if (current_area==AREA_CSEG || + current_area==AREA_GSINIT || + current_area==AREA_XINIT) { + if (num) { + for (i=0; i 15) boob_error(); - out(0x20 + (operand & 15)); - } else { - if (operand > 15) boob_error(); - out(0x30 + (operand & 15)); - } - } -} -*/ - /* turn a string like "10010110b" into an int */ int binary2int(char *str) @@ -367,29 +518,107 @@ int binary2int(char *str) return (sum); } -void print_usage(); - - -/* todo: someday this will allow the user to control where the */ -/* various memory areas go, and it will take care of assigning */ -/* positions to area which follow others (such as OSEG getting */ -/* set just after DSEG on the 2nd and 3rd passes when we have */ -/* leared the size needed for each segment */ +void print_usage(int); void init_areas(void) { - area[AREA_CSEG].alloc_position = 0; - area[AREA_DSEG].alloc_position = 0x30; - area[AREA_OSEG].alloc_position = 0x80; - area[AREA_ISEG].alloc_position = 0; - area[AREA_BSEG].alloc_position = 0; - area[AREA_XSEG].alloc_position = 0; - area[AREA_XISEG].alloc_position = 0; - area[AREA_GSINIT].alloc_position = 0; - area[AREA_GSFINAL].alloc_position = 0; - area[AREA_HOME].alloc_position = 0; + area[AREA_CSEG].start=area[AREA_CSEG].alloc_position = 0; + area[AREA_DSEG].start=area[AREA_DSEG].alloc_position = 0; + area[AREA_BSEG].start=area[AREA_BSEG].alloc_position = 0; + area[AREA_XSEG].start=area[AREA_XSEG].alloc_position = 0; + area[AREA_XISEG].start=area[AREA_XISEG].alloc_position = 0; + area[AREA_XINIT].start=area[AREA_XINIT].alloc_position = 0; + area[AREA_GSINIT].start=area[AREA_GSINIT].alloc_position = 0; + area[AREA_GSFINAL].start=area[AREA_GSFINAL].alloc_position = 0; + area[AREA_HOME].start=area[AREA_HOME].alloc_position = 0; } +void relPrelude() { + //char buffer[132]; + int i, areas=0, globals=0; + struct symbol *p; + + fprintf (frel, "SDCCXA rel, version %1.1f\n", version); + for (i=1; inext) { + if (p->isdef) { + // skip temp labels + if (p->name[strlen(p->name)-1]!='$') { + globals++; + } + } + } + fprintf (frel, "H %d areas %d global symbols\n", areas, globals); + fprintf (frel, "M %s\n", modulename); + for (p=sym_list; p; p=p->next) { + if (!p->isdef) { + fprintf (frel, "S %s Ref0000\n", p->name); + } + } +} + +void printVersion() { + printf("\nPaul's XA51 Assembler\n"); + printf("Copyright 1997,2002 Paul Stoffregen\n\n"); + printf("This program is free software; you can redistribute it\n"); + printf("and/or modify it under the terms of the GNU General Public\n"); + printf("License, Version 2, published by the Free Software Foundation\n\n"); + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); +} + +int verbose=0, createSymbolFile=0; + +void process_args(int argc, char **argv) +{ + int i=0; + + if (argc < 2) print_usage(1); + + while (++i 3) { - if (strncasecmp(infilename+strlen(infilename)-3, ".xa", 3)) - strcat(infilename, ".xa"); - } else strcat(infilename, ".xa"); - strcpy(outfilename, infilename); - outfilename[strlen(outfilename)-3] = '\0'; - strcpy(listfilename, outfilename); - strcat(outfilename, ".hex"); - strcat(listfilename, ".lst"); + process_args (argc, argv); + yyin = fopen(infilename, "r"); if (yyin == NULL) { fprintf(stderr, "Can't open file '%s'.\n", infilename); exit(1); } - fhex = fopen(outfilename, "w"); - if (fhex == NULL) { + frel = fopen(outfilename, "w"); + if (frel == NULL) { fprintf(stderr, "Can't write file '%s'.\n", outfilename); exit(1); } @@ -425,56 +643,66 @@ int main(int argc, char **argv) fprintf(stderr, "Can't write file '%s'.\n", listfilename); exit(1); } + if (createSymbolFile) { + sym_fp = fopen(symfilename, "w"); + if (sym_fp == NULL) { + fprintf(stderr, "Can't write file '%s'.\n", symfilename); + exit(1); + } + } - /* todo: add a command line option to supress verbose messages */ - printf("\nPaul's XA51 Assembler\n"); - printf("Copyright 1997,2002 Paul Stoffregen\n\n"); - printf("This program is free software; you can redistribute it\n"); - printf("and/or modify it under the terms of the GNU General Public\n"); - printf("License, Version 2, published by the Free Software Foundation\n\n"); - printf("This program is distributed in the hope that it will be useful,\n"); - printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); - - - - printf(" Building Symbol Table:\n"); + if (verbose) printf("Pass 1: Building Symbol Table:\n"); p1 = 1; - //mem = 0; init_areas(); yyparse(); flag_targets(); - print_symbol_table(); check_redefine(); + + if (verbose) printf("Pass 2: Aligning Branch Targets:\n"); p1 = 0; p2 = 1; rewind(yyin); yyrestart(yyin); lineno = 1; - printf(" Aligning Branch Targets:\n"); - //mem = 0; init_areas(); yyparse(); - // print_symbol_table(); + + relPrelude(); + if (createSymbolFile) print_symbol_table(); + + if (verbose) printf("Pass 3: Generating Object Code:\n"); p2 = 0; p3 = 1; rewind(yyin); yyrestart(yyin); lineno = 1; - printf(" Generating Object Code:\n"); - //mem = 0; init_areas(); yyparse(); + fclose(yyin); - hexout(0, 0, 1); /* flush and close intel hex file output */ return 0; } -void print_usage() +void print_usage(int fatal) { - fprintf(stderr, "Usage: xa_asm file\n"); - fprintf(stderr, " or xa_asm file.asm\n"); - exit(1); + FILE *out = fatal ? stderr : stdout; + + fprintf (out, "Usage: xa_asm [-s] [-v] file.xa\n"); + fprintf (out, " -v verbose: show progress\n"); + fprintf (out, " -s create symbol file\n"); + fprintf (out, " --version show version/copyright info and exit\n"); + fprintf (out, " --help show this and exit\n"); +#if 0 + // some usefull options I can think of. + fprintf (out, " -m create map file\n"); + fprintf (out, " -ss create symbol file sorted by symbol\n"); + fprintf (out, " -sa create symbol file sorted by segment/address\n"); + fprintf (out, " --no-temps supress temp symbols in map and sym file\n"); + fprintf (out, " --code-loc=# sets the start address of the code\n"); + fprintf (out, " --xdata-loc=# sets the start address of the external data\n"); + fprintf (out, " --stack-loc=# sets the start address of the stack\n"); +#endif + exit(fatal); }