"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 <symbol> [Ref0000 | DefXXXX]" Def's are supposed to be defined in
- their own area/segment
+ "S <symbol> [Ref0000 | DefXXXX | AbsXXXX]" Def's are supposed to be
+ defined in their own area/segment
"A <seg> 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 <how> <symbol>" the relocation info. xx is the offset within the
- previous "T .." line. <how> could be something like REL_FF, REL_FFFF,
- ABS_F0FF. symbol is the (previous) defined symbol it refers to
+ "T xxxx <how> <symbol> 0"
+ "R xxxx <how> <symbol> <pc+>" 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
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;
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},
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; r<MAX_REFS; r++) {
+ if (strcmp(refModes[r], how)==0) {
+ return r;
+ }
+ }
+ return 0;
+}
-struct SEGMENT *findSegment(char *segment) {
- int i;
- for (i=1; i<MAX_SEGMENTS; i++) {
- if (strcmp(segments[i].name, segment)==0) {
- return &segments[i];
+struct SEGMENT *findSegmentByName(char *segment) {
+ int s;
+ for (s=0; s<MAX_SEGMENTS; s++) {
+ if (strcmp(segments[s].name, segment)==0) {
+ return &segments[s];
+ }
+ }
+ return 0;
+}
+
+struct SYMBOL *findSymbolByName(char *symName) {
+ struct SYMBOL *symbol;
+ for (symbol=symbols; symbol; symbol=symbol->next) {
+ if (strcmp(symbol->name, symName)==0) {
+ return symbol;
}
}
return 0;
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;
}
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);
}
FILE *relModule;
char moduleName[PATH_MAX];
int segments, globals;
- int currentLine=1;
+
+ currentLine=1;
if ((relModule=fopen(module, "r"))==NULL) {
perror (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);
}
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;
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);
//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++;
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++;
+ }
+ }
}
}
usage(argv[0], 1);
}
- memset(codeImage, 0xff, CODESIZE);
-
// read in the commands
sprintf (linkCommandsPath, "%s.lnk", argv[1]);
if (!(linkCommandsFile=fopen(linkCommandsPath, "r"))) {
} 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");
+ }
}
}
// 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);
}
}
}
- writeModule();
- return 0;
+ writeModule(outFileName);
+ return fatalErrors? 1 : 0;
}
void error(char *s);
-void RELOC_FF(unsigned pc, unsigned short offset, short rl) {
+void RELOC_FF(unsigned where, unsigned pc, short rl) {
+ // pc = PC of the next instruction
struct symbol *sym;
if ((sym=findSymbol(yytext))) {
if (sym->mode=='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);
}
}
}
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);
$$ = 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 */
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 {
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 '+' ']' {
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;
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);
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 {
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 {
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 {
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;
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) {
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;
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);
}
}
}
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;
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);
}
}
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 */
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 */
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 */
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 */
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 '+' ']' {
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);
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 {
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 {
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);
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 {
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;
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);
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 {
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;
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;
}
}
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;
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;
}
}
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 {
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;
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);
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;
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 {
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;
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 {
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);
}
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 {
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 {
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 {
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);
}