X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fxa51%2Fxa_main.c;h=345ca7e4ec44498a524c0ff0e3430715f88149c7;hb=d08e6df2202ed3f19b681221b502dedb3c6c8a28;hp=da706284161df2f86953f57c0b24559411a522ca;hpb=46c48126418a6f6b861d07cbb8205535cec267f7;p=fw%2Fsdcc diff --git a/as/xa51/xa_main.c b/as/xa51/xa_main.c index da706284..345ca7e4 100644 --- a/as/xa51/xa_main.c +++ b/as/xa51/xa_main.c @@ -17,32 +17,74 @@ /* adapted from the osu8asm project, 1995 */ /* http://www.pjrc.com/tech/osu8/index.html */ +/* + 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[]; struct symbol *sym_list=NULL; struct target *targ_list=NULL; -int lineno=1, mem=0; /* mem is location in memory */ +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=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_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"); +} +/* "mem" is replaced by area[current_area].alloc_position */ +/* int mem=0; */ /* mem is location in memory */ /* add symbols to list when we find their definition in pass #1 */ /* we will evaluate their values in pass #2, and figure out if */ @@ -53,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); @@ -63,6 +114,8 @@ struct symbol * build_sym_list(char *thename) new->isbit = 0; 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; @@ -71,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; @@ -96,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; @@ -121,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); } @@ -175,39 +274,57 @@ void flag_targets() void print_symbol_table() { - struct symbol *p; - p = sym_list; - while (p != NULL) { - printf("Sym:%12s = %5d (%04X) Def:", \ - p->name, p->value, p->value); - if (p->isdef) printf("Yes"); else printf("No "); - printf(" Bit:"); - if (p->isbit) printf("Yes"); else printf("No "); - printf(" Target:"); - if (p->istarget) printf("Yes"); else printf("No "); - printf(" Line %d\n", p->line_def); - p = p->next; - } + struct symbol *p; + p = sym_list; + while (p != NULL) { +#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; + } } /* check that every symbol is in the table only once */ 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) @@ -244,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 */ @@ -262,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); - 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); + } + } + } + } + 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) @@ -347,7 +518,107 @@ int binary2int(char *str) return (sum); } -void print_usage(); +void print_usage(int); + +void init_areas(void) +{ + 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); } @@ -383,53 +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); }