From 00aca2b00c23241366f8c1389543b92597537e70 Mon Sep 17 00:00:00 2001 From: johanknol Date: Tue, 12 Feb 2002 16:34:36 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1921 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- as/xa51/Makefile | 2 +- as/xa51/xa_link.c | 272 ++++++++++++++++++++++---- as/xa51/xa_main.c | 57 ++++-- as/xa51/xa_main.h | 2 + as/xa51/xa_rasm.y | 201 ++++++++++--------- device/examples/xa51/hello.c | 3 + device/examples/xa51/hwinit.c | 4 +- src/xa51/gen.c | 7 +- src/xa51/main.c | 4 +- support/regression/ports/xa51/spec.mk | 2 +- 10 files changed, 387 insertions(+), 167 deletions(-) diff --git a/as/xa51/Makefile b/as/xa51/Makefile index dcd797fe..46d78834 100644 --- a/as/xa51/Makefile +++ b/as/xa51/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -ggdb -O2 -Wall +CFLAGS = -ggdb -Wall YACC = bison -y -d LEX = flex -i LEXLIB = diff --git a/as/xa51/xa_link.c b/as/xa51/xa_link.c index 7c376f15..3284925d 100644 --- a/as/xa51/xa_link.c +++ b/as/xa51/xa_link.c @@ -22,15 +22,16 @@ "SDCCXA rel, version %f" must be the first line, sort of MAGIC word "H %d areas %d global symbols" defines the # of areas and globals - "S [Ref0000 | DefXXXX]" Def's are supposed to be defined in - their own area/segment + "S [Ref0000 | DefXXXX | AbsXXXX]" Def's are supposed to be + defined in their own area/segment "A size %d flags %d" switch to another segment. this can happen multiple times and should be equal. flags is ignored for now - "T xx xx bb bb ..." where xx xx is the address within the current segment - and bb are the bytes - "R xx " the relocation info. xx is the offset within the - previous "T .." line. could be something like REL_FF, REL_FFFF, - ABS_F0FF. symbol is the (previous) defined symbol it refers to + "T xxxx 0" + "R xxxx " the relocation info. xxxx is the address + within relative code space. How is something like REL_FF, REL_FFFF, + ABS_F0FF. Symbol is the referenced symbol and pc+ is the program + counter that will be used to calculate the relative address (that is + the address of the following instruction). So, this is not a standalone linker. It will only link files generated by xa_asm, which will only process files generated by the xa51 sdcc @@ -59,11 +60,40 @@ enum { MAX_SEGMENTS }; +enum { + REL_FF=1, + REL_FFFF, + ABS_0F, + ABS_FF, + ABS_03FF, + ABS_07FF, + ABS_F0FF, + ABS_FFFF, + ABS_0F00FF, + MAX_REFS +}; + +char *refModes[]={ + "???", + "REL_FF", + "REL_FFFF", + "ABS_0F", + "ABS_FF", + "ABS_03FF", + "ABS_07FF", + "ABS_F0FF", + "ABS_FFFF", + "ABS_0F00FF", +}; + #define CODESIZE 0x10000 -char codeImage[CODESIZE]; +int fatalErrors=0; + char gsinitImage[CODESIZE]; +char csegImage[CODESIZE]; char xinitImage[CODESIZE]; +//char gsfinalImage[CODESIZE]; struct SEGMENT { short id; @@ -74,10 +104,10 @@ struct SEGMENT { int current; unsigned char *image; } segments[MAX_SEGMENTS]={ - {0, "????", 0, 0, 0, 0, NULL}, + {0, "???", 0, 0, 0, 0, NULL}, {GSINIT, "GSINIT", 0, 0, 0, 0, gsinitImage}, - {CSEG, "CSEG", 0, 0, 0, 0, codeImage}, + {CSEG, "CSEG", 0, 0, 0, 0, csegImage}, {XINIT, "XINIT", 0, 0, 0, 0, xinitImage}, //{GSFINAL, "GSFINAL", 0, 0, 0, 0, NULL}, @@ -99,27 +129,60 @@ struct MODULE { struct SYMBOL { char *name; struct MODULE *module; + int lineno; struct SEGMENT *segment; + char absolute; int address; struct SYMBOL *next; struct SYMBOL *last; } *symbols=NULL; +struct REFERENCE { + char *name; + struct MODULE *module; + int lineno; + unsigned address, pc; + short how; + struct REFERENCE *next; + struct REFERENCE *last; +} *references=NULL; + char *libPaths[128]; int nlibPaths=0; char *libFiles[128]; int nlibFiles=0; -static char outFileName[PATH_MAX]; +static char outFileName[PATH_MAX]={'\0'}; struct SEGMENT *currentSegment; struct MODULE *currentModule; +int currentLine; + +int howToReference(char *how) { + int r; + for (r=1; rnext) { + if (strcmp(symbol->name, symName)==0) { + return symbol; } } return 0; @@ -144,20 +207,49 @@ void addToModules (char *name) { currentModule=modules->last=module; } -void addToRefs(char *ref) { +void addToRefs(char *ref, int address, char *how, int pc) { + struct REFERENCE *reference; + //fprintf (stderr, "addToRefs: %s\n", ref); + + reference=calloc(1, sizeof(struct REFERENCE)); + reference->name=strdup(ref); + reference->module=currentModule; + reference->lineno=currentLine; + reference->address=address; + reference->how=howToReference(how); + reference->pc=pc; + if (!references) { + references=reference; + } else { + references->last->next=reference; + } + references->last=reference; } -void addToDefs(char *def, int address) { +void addToDefs(char *def, int address, char absolute) { struct SYMBOL *symbol; + /* fprintf (stderr, "addToDefs: %s %s 0x%04x + 0x%04x\n", currentSegment->name, def, currentModule->offset[currentSegment->id], address); */ + + // no duplicates allowed + if ((symbol=findSymbolByName(def))) { + fprintf (stderr, "*** %s:%d duplicate symbol %s first defined in " + "module %s:%d\n", + currentModule->name, currentLine, def, + symbol->module->name, symbol->lineno); + fatalErrors++; + } + symbol=calloc(1, sizeof(struct SYMBOL)); symbol->name=strdup(def); symbol->module=currentModule; + symbol->lineno=currentLine; symbol->segment=currentSegment; + symbol->absolute=absolute; symbol->address=currentModule->offset[currentSegment->id]+address; if (!symbols) { symbols=symbol; @@ -169,7 +261,8 @@ void addToDefs(char *def, int address) { } void syntaxError (char *err) { - fprintf (stderr, "error while parsing '%s'\n", err); + fprintf (stderr, "*** %s:%d error while parsing '%s'\n", + currentModule->name, currentLine, err); exit(1); } @@ -206,7 +299,8 @@ void readModule(char *module) { FILE *relModule; char moduleName[PATH_MAX]; int segments, globals; - int currentLine=1; + + currentLine=1; if ((relModule=fopen(module, "r"))==NULL) { perror (module); @@ -218,11 +312,11 @@ void readModule(char *module) { // first we need to check if this is a valid file if (sscanf(fgets(line, 132, relModule), "SDCCXA rel, version %lf", &hisVersion)!=1) { - fprintf (stderr, "%s is not a valid input file\n", module); + fprintf (stderr, "*** %s is not a valid input file\n", module); exit (1); } if (hisVersion!=version) { - fprintf (stderr, "WARNING: version conflict; " + fprintf (stderr, "*** WARNING: version conflict; " "we(%1.1f) != %s(%1.1f)\n", version, module, hisVersion); } @@ -258,23 +352,23 @@ void readModule(char *module) { int size, flags; if (sscanf(line, "A %[^ ] size %d flags %d", segment, &size, &flags)!=3) { - fprintf (stderr, "%s:%d error in A record line\n", - module, currentLine); - exit (1); + syntaxError(line); } // do we know this segment? - if (!(currentSegment=findSegment(segment))) { - fprintf (stderr, "%s:%d unknown area: %s\n", module, + if (!(currentSegment=findSegmentByName(segment))) { + fprintf (stderr, "*** %s:%d unknown area: %s\n", module, currentLine, segment); exit (1); } if (currentModule->size[currentSegment->id]) { if (currentModule->size[currentSegment->id] != size) { - fprintf (stderr, "%s:%d error %s %d %d\n", + fprintf (stderr, "*** %s:%d error %s size %d != %d\n", module, currentLine, currentSegment->name, currentModule->size[currentSegment->id], size); + } else { + // pleased to meet you again } } else { currentModule->size[currentSegment->id]=size; @@ -290,15 +384,18 @@ void readModule(char *module) { char refdef[132]; unsigned int address; if (sscanf(line, "S %[^ ] %s", symbol, refdef)!=2) { - fprintf (stderr, "%s:%d syntax error near \"%s\"\n", + fprintf (stderr, "*** %s:%d syntax error near \"%s\"\n", module, currentLine, line); exit (1); } if (strncmp(refdef, "Ref", 3)==0) { - addToRefs(symbol); + // we don't need them } else if (strncmp(refdef, "Def", 3)==0) { sscanf (refdef, "Def%04x", &address); - addToDefs(symbol, address); + addToDefs(symbol, address, 0); + } else if (strncmp(refdef, "Abs", 3)==0) { + sscanf (refdef, "Abs%04x", &address); + addToDefs(symbol, address, 1); } else { fprintf (stderr, "%s:%d found invalid symbol definition \"%s\"\n", module, currentLine, line); @@ -335,12 +432,19 @@ void readModule(char *module) { //fprintf (stderr, "\n"); break; } - case 'R': + case 'R': { + unsigned address, from; + char symbol[132]; + char how[32]; //fprintf (stderr, "%s", line); + sscanf (line, "R %x %[^ ] %[^ ] %x", &address, how, symbol, &from); + addToRefs (symbol, address, how, from); break; + } default: - /* fprintf (stderr, "%s:%d unknown record \"%s\"\n", - module, currentLine, line); */ + fprintf (stderr, "%s:%d unknown record \"%s\"\n", + module, currentLine, line); + fatalErrors++; break; } currentLine++; @@ -349,32 +453,108 @@ void readModule(char *module) { fclose (relModule); } -void writeModule() { +void writeModule(char *outFileName) { + FILE *fOut; + fprintf (stderr, "WriteModule: %s\n", outFileName); + if ((fOut=fopen(outFileName, "w"))==NULL) { + perror (outFileName); + } // oops, forgot something :) */ + fclose (fOut); } void relocate() { struct SYMBOL *symbol; + struct REFERENCE *reference; + char *from, *to; int length=segments[GSINIT].current + segments[CSEG].current + segments[XINIT].current; + //fprintf (stderr, "relocate: total code size: 0x%04x\n", length); + // first check if it will fit if (length > 0xffff) { fprintf (stderr, "error: code segment exceeds 0xffff\n"); - exit(1); + fatalErrors++; } - fprintf (stderr, "relocate: total code size: 0x%04x\n", length); // GSINIT gets the --code-loc segments[GSINIT].start=segments[CSEG].start; segments[CSEG].start=segments[GSINIT].start+segments[GSINIT]._size; + // concat cseg to gsinit + from=csegImage; + to=&gsinitImage[segments[GSINIT].start+segments[GSINIT]._size]; + memcpy(to, from, segments[CSEG]._size); segments[XINIT].start=segments[CSEG].start+segments[CSEG]._size; + from=xinitImage; + to+=segments[CSEG]._size; + memcpy(to, from, segments[XINIT]._size); +#if 0 + from=gsfinalImage; + to+=segments[XINIT]._size; + memcpy(to, from, segments[GSFINAL]._size); +#endif segments[XISEG].start=segments[XSEG].start+segments[XINIT]._size; // now relocate the defined symbols for (symbol=symbols; symbol; symbol=symbol->next) { - symbol->address += symbol->segment->start; + if (!symbol->absolute) { + symbol->address += symbol->segment->start; + } + } + // add the segment symbols + currentSegment=findSegmentByName("XINIT"); + addToDefs("s_XINIT", segments[XINIT].start, 0); + addToDefs("l_XINIT", segments[XINIT]._size, 0); + currentSegment=findSegmentByName("XISEG"); + addToDefs("s_XISEG", segments[XISEG].start, 0); + addToDefs("l_XISEG", segments[XISEG]._size, 0); + // and the references + for (reference=references; reference; reference=reference->next) { + if (!(symbol=findSymbolByName(reference->name))) { + fprintf (stderr, "*** %s:%d undefined symbol %s\n", + reference->module->name, reference->lineno, + reference->name); + } else { + reference->address += symbol->segment->start; + switch (reference->how) + { + case REL_FFFF: { + int rel16 = symbol->address-reference->pc; + if (rel16<-65536 || rel16>65534) { + fprintf (stderr, + "rel16 target for %s is out of range in module %s\n", + reference->name, reference->module->name); + fatalErrors++; + } + gsinitImage[reference->address+1]=(rel16/2)>>8; + gsinitImage[reference->address]=rel16/2; + break; + } + case REL_FF: { + int rel8 = symbol->address-reference->pc; + if (rel8<-256 || rel8>256) { + fprintf (stderr, + "rel8 target for %s is out of range in module %s\n", + reference->name, reference->module->name); + fatalErrors++; + } + gsinitImage[reference->address]=rel8/2; + break; + } + case ABS_FFFF: + gsinitImage[reference->address+1] = symbol->address>>8; + // fall through + case ABS_FF: + gsinitImage[reference->address] = symbol->address; + break; + default: + fprintf (stderr, "unsupported reference mode %d.\n", + reference->how); + fatalErrors++; + } + } } } @@ -397,8 +577,6 @@ int main(int argc, char **argv) { usage(argv[0], 1); } - memset(codeImage, 0xff, CODESIZE); - // read in the commands sprintf (linkCommandsPath, "%s.lnk", argv[1]); if (!(linkCommandsFile=fopen(linkCommandsPath, "r"))) { @@ -459,6 +637,12 @@ int main(int argc, char **argv) { } else { // not a switch, must be an inputfile; one/line readModule(linkCommand); + // the first one defines the output name + if (!outFileName[0]) { + strncpy(outFileName, linkCommand, + strlen(linkCommand)-4); + strcat(outFileName, ".hex"); + } } } @@ -478,7 +662,9 @@ int main(int argc, char **argv) { // the symbols for (symbol=symbols; symbol; symbol=symbol->next) { - fprintf (stderr, "%s %s 0x%04x %s\n", symbol->name, symbol->segment->name, + fprintf (stderr, "%s %s %s0x%04x %s\n", symbol->name, + symbol->segment->name, + symbol->absolute ? "= " : "", symbol->address, symbol->module->name); } @@ -492,7 +678,7 @@ int main(int argc, char **argv) { } } - writeModule(); - return 0; + writeModule(outFileName); + return fatalErrors? 1 : 0; } diff --git a/as/xa51/xa_main.c b/as/xa51/xa_main.c index 04ab0e77..ca06f4cf 100644 --- a/as/xa51/xa_main.c +++ b/as/xa51/xa_main.c @@ -200,19 +200,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); } @@ -269,6 +286,8 @@ void print_symbol_table() fprintf (sym_fp, "%-5s", "SFR"); } else if (p->isbit && !p->area) { fprintf (sym_fp, "%-5s", "SBIT"); + } else if (p->mode=='=') { + fprintf (sym_fp,"ABS"); } else if (!p->isdef) { fprintf (sym_fp,"EXTRN"); } else { @@ -388,10 +407,14 @@ void out(int *byte_list, int num) { area[current_area].size); if (!area[current_area].defsEmitted) { for (p=sym_list; p; p=p->next) { - if (p->isdef && p->area==current_area) { + if (p->global && p->isdef && p->area==current_area) { // skip temp labels if (p->name[strlen(p->name)-1]!='$') { - fprintf (frel, "S %s Def%04x\n", p->name, p->value); + 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); + } } } } @@ -405,8 +428,10 @@ void out(int *byte_list, int num) { current_area==AREA_GSFINAL || current_area==AREA_XINIT) { if (num) { - fprintf (frel, "T %04x", MEM_POS); for (i=0; imode=='X') { - sprintf (rel_line[rl], "R %d REL_FF 0x%04x %s", offset, pc, - sym->name); + sprintf (rel_line[rl], "R %04x REL_FF %s %04x", + where, sym->name, pc); } } } -void RELOC_FFFF(unsigned pc, unsigned short offset, short rl) { +void RELOC_FFFF(unsigned where, unsigned pc, short rl) { struct symbol *sym; if ((sym=findSymbol(yytext))) { if (sym->mode=='X') { - sprintf (rel_line[rl], "R %d REL_FFFF 0x%04x %s", offset, pc, - sym->name); + sprintf (rel_line[rl], "R %04x REL_FFFF %s %04x", + where, sym->name, pc); } } } -void RELOC_ABS_0F(unsigned short offset, int expr) { +void RELOC_ABS_0F(unsigned where, int expr) { struct symbol *sym; if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_0F %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_0F %s 0", where, sym->name); } } } -void RELOC_ABS_FF(unsigned short offset, int expr) { +void RELOC_ABS_FF(unsigned where, int expr) { struct symbol *sym; if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_FF %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_FF %s 0", where, sym->name); } } } -void RELOC_ABS_03FF(unsigned short offset, int expr) { +void RELOC_ABS_03FF(unsigned where, int expr) { struct symbol *sym; if (expr_var[0]) { if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_03FF %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_03FF %s 0", where, sym->name); } } } } -void RELOC_ABS_07ff(unsigned short offset, int expr) { +void RELOC_ABS_07ff(unsigned where, int expr) { struct symbol *sym; if (expr_var[0]) { if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_07ff %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_07ff %s 0", where, sym->name); } } } } -void RELOC_ABS_F0FF(unsigned short offset, int expr) { +void RELOC_ABS_F0FF(unsigned where, int expr) { struct symbol *sym; if (expr_var[0]) { if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_F0FF %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_F0FF %s", where, sym->name); } } } } -void RELOC_ABS_FFFF(unsigned short offset, int expr) { +void RELOC_ABS_FFFF(unsigned where, int expr) { struct symbol *sym; if (expr_var[0]) { if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { -#if 1 - sprintf (rel_line[expr], "R %d ABS_FFFF %s", offset, sym->name); -#else - sprintf (rel_line[expr], "R 0 0 00 %02x 02 %02x %02x", current_area, - (sym->lk_index>>8)&0xff, sym->lk_index&&0xff); -#endif + sprintf (rel_line[expr], "R %04x ABS_FFFF %s 0", where, sym->name); } } } } -void RELOC_ABS_0F00FF(unsigned short offset, int expr) { +void RELOC_ABS_0F00FF(unsigned where, int expr) { struct symbol *sym; if (expr_var[0]) { if ((sym=findSymbol(expr_var[expr]))) { if (sym->mode=='X') { - sprintf (rel_line[expr], "R %d ABS_0F00FF %s", offset, sym->name); + sprintf (rel_line[expr], "R %04x ABS_0F00FF %s", where, sym->name); } } } @@ -209,9 +205,9 @@ directive: '.' ORG expr { if (p1 || p2) assign_value(symbol_name, $5, '?'); $$ = 0; } - | normal_or_bit_symbol '=' expr { + | symbol '=' expr { if (p1) build_sym_list(symbol_name); - if (p1 || p2) assign_value(symbol_name, $3, '?'); + if (p1 || p2) assign_value(symbol_name, $3, '='); } | symbol SFR expr { if (p1) build_sym_list(symbol_name); @@ -279,12 +275,13 @@ directive: '.' ORG expr { $$ = 0; } | '.' GLOBL WORD { + mk_global(lex_sym_name); /* ignore global symbol declaration */ $$ = 0; } | '.' GLOBL bit { /* ignore bit symbol declaration */ - $$ = 0; + $$ = 0; } | '.' DS expr { /* todo: if CSEG, emit some filler bytes */ @@ -465,14 +462,14 @@ instruction: op[0] = arith_opcode * 16 + size * 8 + 4; op[1] = reg($2) * 16 + reg_indirect($5); op[2] = ($7 >= 0) ? $7 : 256 + $7; - RELOC_ABS_FF(2,0); + RELOC_ABS_FF(MEM_POS+2,0); } else { $$ = 4; op[0] = arith_opcode * 16 + size * 8 + 5; op[1] = reg($2) * 16 + reg_indirect($5); op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7); op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7); - RELOC_ABS_FFFF(2,0); + RELOC_ABS_FFFF(MEM_POS+2,0); } } | arith_inst '[' REG '+' expr ']' ',' REG { @@ -482,14 +479,14 @@ instruction: op[0] = arith_opcode * 16 + size * 8 + 4; op[1] = reg($8) * 16 + 8 + reg_indirect($3); op[2] = ($5 >= 0) ? $5 : 256 + $5; - RELOC_ABS_FF(2,0); + RELOC_ABS_FF(MEM_POS+2,0); } else { $$ = 4; op[0] = arith_opcode * 16 + size * 8 + 5; op[1] = reg($8) * 16 + 8 + reg_indirect($3); op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5); op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5); - RELOC_ABS_FFFF(2,0); + RELOC_ABS_FFFF(MEM_POS+2,0); } } | arith_inst REG ',' '[' REG '+' ']' { @@ -510,7 +507,7 @@ instruction: op[0] = arith_opcode * 16 + size * 8 + 6; op[1] = reg($4) * 16 + 8 + msb(direct_addr($2)); op[2] = lsb(direct_addr($2)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | arith_inst REG ',' WORD { $$ = 3; @@ -518,7 +515,7 @@ instruction: op[0] = arith_opcode * 16 + size * 8 + 6; op[1] = reg($2) * 16 + msb(direct_addr($4)); op[2] = lsb(direct_addr($4)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | arith_inst REG ',' '#' expr { size = find_size1(inst_size, $2); @@ -527,14 +524,14 @@ instruction: op[0] = 0x91; op[1] = reg($2) * 16 + arith_opcode; op[2] = imm_data8($5); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); } else { $$ = 4; op[0] = 0x99; op[1] = reg($2) * 16 + arith_opcode; op[2] = msb(imm_data16($5)); op[3] = lsb(imm_data16($5)); - RELOC_ABS_FFFF (2, 0); + RELOC_ABS_FFFF (MEM_POS+2, 0); } } | arith_inst '[' REG ']' ',' '#' expr { @@ -544,14 +541,14 @@ instruction: op[0] = 0x92; op[1] = reg_indirect($3) * 16 + arith_opcode; op[2] = imm_data8($7); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); } else { $$ = 4; op[0] = 0x9A; op[1] = reg_indirect($3) * 16 + arith_opcode; op[2] = msb(imm_data16($7)); op[3] = lsb(imm_data16($7)); - RELOC_ABS_FFFF (2, 0); + RELOC_ABS_FFFF (MEM_POS+2, 0); } } | arith_inst '[' REG '+' ']' ',' '#' expr { @@ -561,14 +558,14 @@ instruction: op[0] = 0x93; op[1] = reg_indirect($3) * 16 + arith_opcode; op[2] = imm_data8($8); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); } else { $$ = 4; op[0] = 0x9B; op[1] = reg_indirect($3) * 16 + arith_opcode; op[2] = msb(imm_data16($8)); op[3] = lsb(imm_data16($8)); - RELOC_ABS_FFFF (2, 0); + RELOC_ABS_FFFF (MEM_POS+2, 0); } } | arith_inst '[' REG '+' expr ']' ',' '#' expr { @@ -580,8 +577,8 @@ instruction: op[1] = reg_indirect($3) * 16 + arith_opcode; op[2] = ($5 >= 0) ? $5 : 256 + $5; op[3] = imm_data8($9); - RELOC_ABS_FF(2, 0); - RELOC_ABS_FF(3, 1); + RELOC_ABS_FF(MEM_POS+2, 0); + RELOC_ABS_FF(MEM_POS+3, 1); } else { $$ = 5; op[0] = 0x9C; @@ -589,8 +586,8 @@ instruction: op[2] = ($5 >= 0) ? $5 : 256 + $5; op[3] = msb(imm_data16($9)); op[4] = lsb(imm_data16($9)); - RELOC_ABS_FF(2, 0); - RELOC_ABS_FFFF(3, 1); + RELOC_ABS_FF(MEM_POS+2, 0); + RELOC_ABS_FFFF(MEM_POS+3, 1); } } else { if (size == SIZE8) { @@ -600,8 +597,8 @@ instruction: op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5); op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5); op[4] = imm_data8($9); - RELOC_ABS_FFFF(2,0); - RELOC_ABS_FF(4,1); + RELOC_ABS_FFFF(MEM_POS+2,0); + RELOC_ABS_FF(MEM_POS+4,1); } else { $$ = 6; op[0] = 0x9D; @@ -610,8 +607,8 @@ instruction: op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5); op[4] = msb(imm_data16($9)); op[5] = lsb(imm_data16($9)); - RELOC_ABS_FFFF(2, 0); - RELOC_ABS_FFFF(4, 1); + RELOC_ABS_FFFF(MEM_POS+2, 0); + RELOC_ABS_FFFF(MEM_POS+4, 1); } } } @@ -623,8 +620,8 @@ instruction: op[1] = msb(direct_addr($2)) * 16 + arith_opcode; op[2] = lsb(direct_addr($2)); op[3] = imm_data8($5); - RELOC_ABS_F0FF(1,0); - RELOC_ABS_FF(3,1); + RELOC_ABS_F0FF(MEM_POS+1,0); + RELOC_ABS_FF(MEM_POS+3,1); } else { $$ = 5; op[0] = 0x9E; @@ -632,8 +629,8 @@ instruction: op[2] = lsb(direct_addr($2)); op[3] = msb(imm_data16($5)); op[4] = lsb(imm_data16($5)); - RELOC_ABS_F0FF(1,0); - RELOC_ABS_FFFF (3,1); + RELOC_ABS_F0FF(MEM_POS+1,0); + RELOC_ABS_FFFF (MEM_POS+3,1); } } @@ -658,7 +655,7 @@ instruction: op[0] = 0xA0 + size * 8; op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2)); op[2] = lsb(direct_addr($2)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | arith_inst '[' REG ']' ',' WORD { /* this addr mode is only valid for MOV */ @@ -668,7 +665,7 @@ instruction: op[0] = 0xA0 + size * 8; op[1] = reg_indirect($3) * 16 + msb(direct_addr($6)); op[2] = lsb(direct_addr($6)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | arith_inst WORD ',' WORD { /* this addr mode is only valid for MOV */ @@ -679,8 +676,8 @@ instruction: op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4)); op[2] = lsb(direct_addr($2)); op[3] = lsb(direct_addr($4)); - RELOC_ABS_F0FF(1, 0); - RELOC_ABS_0F00FF(1, 1); + RELOC_ABS_F0FF(MEM_POS+1, 0); + RELOC_ABS_0F00FF(MEM_POS+1, 1); } | arith_inst REG ',' USP { /* this addr mode is only valid for MOV */ @@ -703,7 +700,7 @@ instruction: op[0] = 0x08; op[1] = 0x20 + msb(bit_addr($4)); op[2] = lsb(bit_addr($4)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | arith_inst bit ',' C { /* this addr mode is only valid for MOV */ @@ -712,7 +709,7 @@ instruction: op[0] = 0x08; op[1] = 0x30 + msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | MOVC REG ',' '[' REG '+' ']' { @@ -761,28 +758,28 @@ instruction: op[0] = 0xA0 + size * 8; op[1] = reg($2) * 16 + msb(direct_addr($4)); op[2] = lsb(direct_addr($4)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | short_data_inst REG ',' '#' expr { $$ = 2; size = find_size1(inst_size, $2); op[0] = short_opcode + size * 8 + 1; op[1] = reg($2) * 16 + imm_data4_signed($5); - RELOC_ABS_0F(1, 0); + RELOC_ABS_0F(MEM_POS+1, 0); } | short_data_inst '[' REG ']' ',' '#' expr { $$ = 2; size = find_size0(inst_size); op[0] = short_opcode + size * 8 + 2; op[1] = reg_indirect($3) * 16 + imm_data4_signed($7); - RELOC_ABS_0F(1, 0); + RELOC_ABS_0F(MEM_POS+1, 0); } | short_data_inst '[' REG '+' ']' ',' '#' expr { $$ = 2; size = find_size0(inst_size); op[0] = short_opcode + size * 8 + 3; op[1] = reg_indirect($3) * 16 + imm_data4_signed($8); - RELOC_ABS_0F(1, 0); + RELOC_ABS_0F(MEM_POS+1, 0); } | short_data_inst '[' REG '+' expr ']' ',' '#' expr { size = find_size0(inst_size); @@ -791,16 +788,16 @@ instruction: op[0] = short_opcode + size * 8 + 4; op[1] = reg_indirect($3) * 16 + imm_data4_signed($9); op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5; - RELOC_ABS_0F(1, 1); - RELOC_ABS_FF(2, 0); + RELOC_ABS_0F(MEM_POS+1, 1); + RELOC_ABS_FF(MEM_POS+2, 0); } else { $$ = 4; op[0] = short_opcode + size * 8 + 5; op[1] = reg_indirect($3) * 16 + imm_data4_signed($9); op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5); op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5); - RELOC_ABS_0F(1, 1); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_0F(MEM_POS+1, 1); + RELOC_ABS_FFFF(MEM_POS+2, 0); } } | short_data_inst expr ',' '#' expr { @@ -809,21 +806,21 @@ instruction: op[0] = short_opcode + size * 8 + 6; op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5); op[2] = lsb(direct_addr($2)); - RELOC_ABS_0F(1, 0); + RELOC_ABS_0F(MEM_POS+1, 0); } | ANL C ',' bit { $$ = 3; op[0] = 0x08; op[1] = 0x40 + msb(bit_addr($4)); op[2] = lsb(bit_addr($4)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | ANL C ',' '/' bit { $$ = 3; op[0] = 0x08; op[1] = 0x50 + msb(bit_addr($5)); op[2] = lsb(bit_addr($5)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | ORL C ',' bit { @@ -831,28 +828,28 @@ instruction: op[0] = 0x08; op[1] = 0x60 + msb(bit_addr($4)); op[2] = lsb(bit_addr($4)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | ORL C ',' '/' bit { $$ = 3; op[0] = 0x08; op[1] = 0x70 + msb(bit_addr($5)); op[2] = lsb(bit_addr($5)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | CLR bit { $$ = 3; op[0] = 0x08; op[1] = msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | SETB bit { $$ = 3; op[0] = 0x08; op[1] = 0x10 + msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); - RELOC_ABS_03FF(1, 0); + RELOC_ABS_03FF(MEM_POS+1, 0); } | logical_shift_inst REG ',' REG { size = find_size1(inst_size, $2); @@ -937,13 +934,13 @@ instruction: op[0] = 0x40; op[1] = reg($2) * 16 + reg_indirect($4); op[2] = ($6 >= 0) ? $6 : 256 + $6; - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); } else { op[0] = 0x48; op[1] = reg($2) * 16 + reg_indirect($4); op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6); op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_FFFF(MEM_POS+2, 0); } } | stack_inst WORD { @@ -952,7 +949,7 @@ instruction: op[0] = msb(stack_addr_opcode) + size * 8; op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2)); op[2] = lsb(direct_addr($2)); - RELOC_ABS_07ff(1, 0); + RELOC_ABS_07ff(MEM_POS+1, 0); } | stack_inst rlist { $$ = 2; @@ -987,7 +984,7 @@ instruction: op[1] = reg($2) + 8; op[2] = msb(imm_data16($5)); op[3] = lsb(imm_data16($5)); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_FFFF(MEM_POS+2, 0); } | MULU REG ',' '#' expr { size = find_size2(inst_size, $2, $4); @@ -996,14 +993,14 @@ instruction: op[0] = 0xE8; op[1] = reg($2) * 16; op[2] = imm_data8($5); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); } else { $$ = 4; op[0] = 0xE9; op[1] = reg($2) * 16; op[2] = msb(imm_data16($5)); op[3] = lsb(imm_data16($5)); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_FFFF(MEM_POS+2, 0); } } | DIV REG ',' REG { @@ -1050,7 +1047,7 @@ instruction: op[0] = 0xE8; op[1] = reg($2) * 16 + 11; op[2] = imm_data8($5); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); break; case SIZE32: $$ = 4; @@ -1058,7 +1055,7 @@ instruction: op[1] = (reg($2) / 2) * 32 + 9; op[2] = msb(imm_data16($5)); op[3] = lsb(imm_data16($5)); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_FFFF(MEM_POS+2, 0); break; } } @@ -1070,14 +1067,14 @@ instruction: op[0] = 0xE8; op[1] = reg($2) * 16 + 1; op[2] = imm_data8($5); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); break; case SIZE16: $$ = 3; op[0] = 0xE8; op[1] = reg($2) * 16 + 3; op[2] = imm_data8($5); - RELOC_ABS_FF(2, 0); + RELOC_ABS_FF(MEM_POS+2, 0); break; case SIZE32: $$ = 4; @@ -1085,7 +1082,7 @@ instruction: op[1] = (reg($2) / 2) * 32 + 1; op[2] = msb(imm_data16($5)); op[3] = lsb(imm_data16($5)); - RELOC_ABS_FFFF(2, 0); + RELOC_ABS_FFFF(MEM_POS+2, 0); break; } } @@ -1129,7 +1126,7 @@ instruction: op[0] = 0xD5; op[1] = msb(rel16(MEM_POS + $$, $2)); op[2] = lsb(rel16(MEM_POS + $$, $2)); - RELOC_FFFF(MEM_POS+$$,1,0); + RELOC_FFFF(MEM_POS+1,MEM_POS+$$,0); } | CALL jmpaddr { @@ -1137,13 +1134,13 @@ instruction: op[0] = 0xC5; op[1] = msb(rel16(MEM_POS + $$, $2)); op[2] = lsb(rel16(MEM_POS + $$, $2)); - RELOC_FFFF(MEM_POS+$$,1,0); + RELOC_FFFF(MEM_POS+1, MEM_POS+$$, 0); } | branch_inst jmpaddr { $$ = 2; op[0] = branch_opcode; op[1] = rel8(MEM_POS + $$, $2); - RELOC_FF(MEM_POS + $$, 1,0); + RELOC_FF(MEM_POS+1,MEM_POS + $$, 0); } | CJNE REG ',' expr ',' jmpaddr { $$ = 4; @@ -1152,8 +1149,8 @@ instruction: op[1] = reg($2) * 16 + msb(direct_addr($4)); op[2] = lsb(direct_addr($4)); op[3] = rel8(MEM_POS + $$, $6); - RELOC_ABS_07ff(1, 0); - RELOC_FF(MEM_POS + $$, 3,1); + RELOC_ABS_07ff(MEM_POS+1, 0); + RELOC_FF(MEM_POS+3, MEM_POS + $$, 1); } | CJNE REG ',' '#' expr ',' jmpaddr { size = find_size1(inst_size, $2); @@ -1163,7 +1160,7 @@ instruction: op[1] = reg($2) * 16; op[2] = rel8(MEM_POS + $$, $7); op[3] = imm_data8($5); - RELOC_ABS_FF(3, 0); + RELOC_ABS_FF(MEM_POS+3, 0); } else { $$ = 5; op[0] = 0xEB; @@ -1171,7 +1168,7 @@ instruction: op[2] = rel8(MEM_POS + $$, $7); op[3] = msb(imm_data16($5)); op[4] = lsb(imm_data16($5)); - RELOC_ABS_FFFF(3, 0); + RELOC_ABS_FFFF(MEM_POS+3, 0); } } | CJNE '[' REG ']' ',' '#' expr ',' jmpaddr { @@ -1182,7 +1179,7 @@ instruction: op[1] = reg_indirect($3) * 16 + 8; op[2] = rel8(MEM_POS + $$, $9); op[3] = imm_data8($7); - RELOC_ABS_FF(3, 0); + RELOC_ABS_FF(MEM_POS+3, 0); } else { $$ = 5; op[0] = 0xEB; @@ -1190,7 +1187,7 @@ instruction: op[2] = rel8(MEM_POS + $$, $9); op[3] = msb(imm_data16($7)); op[4] = lsb(imm_data16($7)); - RELOC_ABS_FFFF(3, 0); + RELOC_ABS_FFFF(MEM_POS+3, 0); } } | DJNZ REG ',' jmpaddr { @@ -1199,7 +1196,7 @@ instruction: op[0] = 0x87 + size * 8; op[1] = reg($2) * 16 + 8; op[2] = rel8(MEM_POS + $$, $4); - RELOC_FF(MEM_POS+$$, 2, 0); + RELOC_FF(MEM_POS+2, MEM_POS+$$, 0); } @@ -1210,8 +1207,8 @@ instruction: op[1] = msb(direct_addr($2)) + 8; op[2] = lsb(direct_addr($2)); op[3] = rel8(MEM_POS + $$, $4); - RELOC_ABS_07ff(1, 0); - RELOC_FF(MEM_POS + $$, 3, 1) + RELOC_ABS_07ff(MEM_POS+1, 0); + RELOC_FF(MEM_POS+3, MEM_POS + $$, 1) } | JB bit ',' jmpaddr { @@ -1220,8 +1217,8 @@ instruction: op[1] = 0x80 + msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); op[3] = rel8(MEM_POS + $$, $4); - RELOC_ABS_03FF(1, 0); - RELOC_FF(MEM_POS + $$, 3, 1); + RELOC_ABS_03FF(MEM_POS+1, 0); + RELOC_FF(MEM_POS+3, MEM_POS + $$, 1); } | JBC bit ',' jmpaddr { @@ -1230,8 +1227,8 @@ instruction: op[1] = 0xC0 + msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); op[3] = rel8(MEM_POS + $$, $4); - RELOC_ABS_03FF(1, 0); - RELOC_FF(MEM_POS + $$, 3, 1); + RELOC_ABS_03FF(MEM_POS+1, 0); + RELOC_FF(MEM_POS+3, MEM_POS + $$, 1); } | JNB bit ',' jmpaddr { @@ -1240,8 +1237,8 @@ instruction: op[1] = 0xA0 + msb(bit_addr($2)); op[2] = lsb(bit_addr($2)); op[3] = rel8(MEM_POS + $$, $4); - RELOC_ABS_03FF(1, 0); - RELOC_FF(MEM_POS + $$, 3, 1); + RELOC_ABS_03FF(MEM_POS+1, 0); + RELOC_FF(MEM_POS+3, MEM_POS + $$, 1); } diff --git a/device/examples/xa51/hello.c b/device/examples/xa51/hello.c index 9a575b4b..c7906cd0 100755 --- a/device/examples/xa51/hello.c +++ b/device/examples/xa51/hello.c @@ -9,9 +9,12 @@ extern bit be; extern code ce; extern data de; extern xdata xe; +xdata at 0x1234 abs; +extern xdata xee; void main(void) { xe=getchar(); + abs=1; putchar('1'); putchar('2'); putchar('3'); diff --git a/device/examples/xa51/hwinit.c b/device/examples/xa51/hwinit.c index a408bc1b..b7c79876 100755 --- a/device/examples/xa51/hwinit.c +++ b/device/examples/xa51/hwinit.c @@ -42,7 +42,9 @@ void putchar(char c) { _endasm; } -#define getchar(x) +char getchar() { + return 0; +} void exit_simulator(void) { _asm diff --git a/src/xa51/gen.c b/src/xa51/gen.c index 14190ca0..73951801 100755 --- a/src/xa51/gen.c +++ b/src/xa51/gen.c @@ -1698,7 +1698,12 @@ static void genCast (iCode * ic) { if (size==2) return; // fall through: case 0x41 - emitcode("sext", AOP_NAME(result)[1]); + if (signedness) { + emitcode("sext", "r1"); + } else { + emitcode("mov", "r1,#0"); + } + emitcode("mov", "%s,r1", AOP_NAME(result)[1]); return; case 0x14: case 0x12: diff --git a/src/xa51/main.c b/src/xa51/main.c index 43bd771b..0c1584b2 100755 --- a/src/xa51/main.c +++ b/src/xa51/main.c @@ -198,7 +198,7 @@ static const char *_linkCmd[] = /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */ static const char *_asmCmd[] = { - "xa_rasm", "$l", "$3", "$1.xa", NULL + "xa_rasm", "$l", "$3", "$1.asm", NULL }; /* Globals */ @@ -218,7 +218,7 @@ PORT xa51_port = "", /* Options with debug */ "", /* Options without debug */ 0, - ".xa", + ".asm", NULL /* no do_assemble function */ }, { diff --git a/support/regression/ports/xa51/spec.mk b/support/regression/ports/xa51/spec.mk index 39b98d7d..a235690c 100755 --- a/support/regression/ports/xa51/spec.mk +++ b/support/regression/ports/xa51/spec.mk @@ -8,7 +8,7 @@ SXA = $(shell if [ -f $(SXA_A) ]; then echo $(SXA_A); else echo $(SXA_B); fi) SDCCFLAGS +=-mxa51 --lesspedantic -DREENTRANT= -OBJEXT = .xa +OBJEXT = .rel EXEEXT = .hex EXTRAS = fwk/lib/testfwk$(OBJEXT) $(PORTS_DIR)/$(PORT)/support$(OBJEXT) -- 2.30.2