"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
+ ABS_70FF. 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).
enum {
REL_FF=1,
REL_FFFF,
+ BIT_03FF,
+ DIR_07FF,
+ DIR_70FF,
+ DIR_0700FF,
ABS_0F,
ABS_FF,
- ABS_03FF,
- ABS_07FF,
- ABS_F0FF,
ABS_FFFF,
- ABS_0F00FF,
+ ABS_PC,
MAX_REFS
};
"???",
"REL_FF",
"REL_FFFF",
+ "BIT_03FF",
+ "DIR_07FF",
+ "DIR_70FF",
+ "DIR_0700FF",
"ABS_0F",
"ABS_FF",
- "ABS_03FF",
- "ABS_07FF",
- "ABS_F0FF",
"ABS_FFFF",
- "ABS_0F00FF",
+ "ABS_PC"
};
#define CODESIZE 0x10000
struct REFERENCE {
char *name;
struct MODULE *module;
+ struct SEGMENT *segment;
int lineno;
unsigned address, pc;
short how;
reference=calloc(1, sizeof(struct REFERENCE));
reference->name=strdup(ref);
reference->module=currentModule;
+ reference->segment=currentSegment;
reference->lineno=currentLine;
reference->address=address;
reference->how=howToReference(how);
+ if (reference->how==ABS_PC) {
+ reference->resolved=1;
+ }
reference->pc=pc;
if (!references) {
references=reference;
void resolve() {
struct REFERENCE *reference;
for (reference=references; reference; reference=reference->next) {
- if (findSymbolByName(reference->name)) {
+ if ((reference->how==ABS_PC) || findSymbolByName(reference->name)) {
reference->resolved=1;
}
}
if ((fOut=fopen(outFileName, "w"))==NULL) {
perror (outFileName);
}
- fprintf (fOut, "Just for now, make it a little bit more readable\n");
while (size) {
len = size>16 ? 16 : size;
size-=len;
- fprintf (fOut, ":%02X.%04X.%02X >", len, address, 0);
+ fprintf (fOut, ":%02X%04X%02X", len, address, 0);
checksum = len + (address>>8) + (address&0xff);
while (len--) {
checksum += gsfinalImage[address];
- fprintf (fOut, " %02X", gsfinalImage[address++]);
+ fprintf (fOut, "%02X", gsfinalImage[address++]);
}
checksum &= 0xff;
if (checksum) {
checksum = 0x100 - checksum;
}
- fprintf (fOut, " < %02X\n", checksum);
+ fprintf (fOut, "%02X\n", checksum);
}
fprintf (fOut, ":00000001FF\n");
}
// and the references
for (reference=references; reference; reference=reference->next) {
- if (!(symbol=findSymbolByName(reference->name))) {
- // this reference isn't defined after all
+ symbol=findSymbolByName(reference->name);
+ if (!reference->resolved && !symbol && reference->how!=ABS_PC) {
+ // this reference isn't resolved after all
fprintf (stderr, "*** %s:%d undefined symbol %s\n",
reference->module->name, reference->lineno,
reference->name);
fatalErrors++;
} else {
- reference->address += symbol->segment->start;
- reference->pc += symbol->segment->start;
+ reference->address +=
+ reference->module->offset[reference->segment->id]+
+ reference->segment->start;
+ reference->pc +=
+ reference->module->offset[reference->segment->id]+
+ reference->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",
+ case REL_FF: {
+ int rel8 = symbol->address-(reference->pc & ~1);
+ 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+1]=(rel16/2)>>8;
- gsinitImage[reference->address]=rel16/2;
+ gsfinalImage[reference->address]=rel8/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",
+ case REL_FFFF: {
+ int rel16 = symbol->address-(reference->pc & ~1);
+ 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]=rel8/2;
+ gsfinalImage[reference->address]=(rel16/2)>>8;
+ gsfinalImage[reference->address+1]=rel16/2;
break;
}
+ case DIR_70FF:
+ gsfinalImage[reference->address] = (symbol->address<<4)&0x70;
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
case ABS_FFFF:
- gsinitImage[reference->address+1] = symbol->address>>8;
- // fall through
+ gsfinalImage[reference->address] = symbol->address>>8;
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
case ABS_FF:
- gsinitImage[reference->address] = symbol->address;
+ gsfinalImage[reference->address] = symbol->address;
+ break;
+ case ABS_PC:
+ {
+ unsigned int address=
+ (gsfinalImage[reference->address]<<8) +
+ gsfinalImage[reference->address+1];
+ address += reference->module->offset[reference->segment->id];
+ address += segments[reference->segment->id].start;
+ gsfinalImage[reference->address] = address>>8;
+ gsfinalImage[reference->address+1] = address;
+ };
break;
default:
fprintf (stderr, "unsupported reference mode %d.\n",
int rlist_reg_bank, rlist_bitmask, rlist_size;
int db_count, dw_count, i;
char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
-char expr_var[2][MAX_SYMBOL]={{'\0'},{'\0'}};
+char operand[2][MAX_SYMBOL]={{'\0'},{'\0'}};
extern char lex_sym_name[];
extern int yylex();
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') {
+ if ((sym=findSymbol(operand[0]))) {
+ if (sym->mode=='X' || sym->area!=current_area) {
sprintf (rel_line[rl], "R %04x REL_FF %s %04x",
where, sym->name, pc);
}
void RELOC_FFFF(unsigned where, unsigned pc, short rl) {
struct symbol *sym;
- if ((sym=findSymbol(yytext))) {
- if (sym->mode=='X') {
+ if ((sym=findSymbol(operand[0]))) {
+ if (sym->mode=='X' || sym->area!=current_area) {
sprintf (rel_line[rl], "R %04x REL_FFFF %s %04x",
where, sym->name, pc);
}
}
}
-void RELOC_ABS_0F(unsigned where, int expr) {
+void RELOC_ABS_0F(unsigned where, int seq) {
struct symbol *sym;
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_0F %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x ABS_0F %s 0", where, sym->name);
}
}
-void RELOC_ABS_FF(unsigned where, int expr) {
+void RELOC_BIT_03FF(unsigned where, int seq) {
struct symbol *sym;
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_FF %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x BIT_03FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_03FF(unsigned where, int expr) {
+void RELOC_DIR_07FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_03FF %s 0", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_07FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_07ff(unsigned where, int expr) {
+void RELOC_DIR_70FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_07ff %s 0", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_70FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_F0FF(unsigned where, int expr) {
+void RELOC_ABS_FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_F0FF %s", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_FF %s 0", where, sym->name);
}
}
-
-void RELOC_ABS_FFFF(unsigned where, int expr) {
+
+void RELOC_ABS_FFFF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_FFFF %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq]))) {
+ switch (sym->mode) {
+ case 'A':
+ // sfr or sbit, already in instruction
+ case '=':
+ // equat, already in instruction
+ break;
+ case 'X':
+ // external reference
+ sprintf (rel_line[seq], "R %04x ABS_FFFF %s %04x", where, sym->name,
+ sym->value);
+ break;
+ case 'R':
+ // absolute in current segment
+ sprintf (rel_line[seq], "R %04x ABS_PC PC %04x", where, sym->value);
+ break;
+ default:
+ fprintf (stderr, "unknown ABS_FFFF\n");
+ exit (1);
}
}
}
-void RELOC_ABS_0F00FF(unsigned where, int expr) {
+void RELOC_DIR_0700FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_0F00FF %s", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x ABS_0700FF %s 0", where, sym->name);
}
}
%nonassoc UNARY
%%
-
all: line
| line all;
value: NUMBER {$$ = $1;}
| CHAR {$$ = $1;}
- | WORD {
- $$ = $1;
- if (expr_var[0][0]=='\0') {
- strcpy(expr_var[0], yytext);
- } else {
- strcpy(expr_var[1], yytext);
- }
- }
-
+ | WORD { $$ = $1;}
rlist: REG {
rlist_bitmask = 1<<(reg($1) % 8);
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(MEM_POS+1, 0);
+ RELOC_DIR_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(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| arith_inst REG ',' '#' expr {
size = find_size1(inst_size, $2);
op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
op[2] = lsb(direct_addr($2));
op[3] = imm_data8($5);
- RELOC_ABS_F0FF(MEM_POS+1,0);
+ RELOC_DIR_70FF(MEM_POS+1,0);
RELOC_ABS_FF(MEM_POS+3,1);
} else {
$$ = 5;
op[2] = lsb(direct_addr($2));
op[3] = msb(imm_data16($5));
op[4] = lsb(imm_data16($5));
- RELOC_ABS_F0FF(MEM_POS+1,0);
+ RELOC_DIR_70FF(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(MEM_POS+1, 0);
+ RELOC_DIR_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(MEM_POS+1, 0);
+ RELOC_DIR_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(MEM_POS+1, 0);
- RELOC_ABS_0F00FF(MEM_POS+1, 1);
+ RELOC_DIR_70FF(MEM_POS+1, 0);
+ RELOC_DIR_0700FF(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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| short_data_inst REG ',' '#' expr {
$$ = 2;
op[0] = 0x08;
op[1] = 0x40 + msb(bit_addr($4));
op[2] = lsb(bit_addr($4));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_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(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| logical_shift_inst REG ',' REG {
size = find_size1(inst_size, $2);
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(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| stack_inst rlist {
$$ = 2;
size = find_size2(inst_size, $2, $4);
switch (size) {
case SIZE8:
- error("Singed DIV can't be 8 bit size"); break;
+ error("Signed DIV can't be 8 bit size"); break;
case SIZE16:
op[0] = 0xE7;
op[1] = reg($2) * 16 + reg($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(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
| CJNE REG ',' '#' expr ',' jmpaddr {
op[1] = msb(direct_addr($2)) + 8;
op[2] = lsb(direct_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1)
}
op[1] = 0x80 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
op[1] = 0xC0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
op[1] = 0xA0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}