From: kvigor Date: Tue, 8 Feb 2000 20:57:34 +0000 (+0000) Subject: More 24 bit flat mode support: handles "expr >> 16" relocations X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=e84c096709aa5210c71156dee96fea5e3c661f11;p=fw%2Fsdcc More 24 bit flat mode support: handles "expr >> 16" relocations git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@89 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/as/doc/format.txt b/as/doc/format.txt index fa73cfe2..0cc625ef 100644 --- a/as/doc/format.txt +++ b/as/doc/format.txt @@ -67,24 +67,43 @@ 2.5.7 R Line - R 0 0 nn nn n1 n2 xx xx ... + R 0 0 nn nn n1 [n1x] n2 xx xx ... The R line provides the relocation information to the linker. The nn nn value is the current area index, i.e. which area the current values were assembled. Relocation information is en- - coded in groups of 4 bytes: + coded in groups of 4 (possibly 5) bytes: - 1. n1 is the relocation mode and object format + 1. n1 (and optionally n1x) is the relocation mode and object + format: 1. bit 0 word(0x00)/byte(0x01) 2. bit 1 relocatable area(0x00)/symbol(0x02) 3. bit 2 normal(0x00)/PC relative(0x04) relocation - 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for + 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for byte data 5. bit 4 signed(0x00)/unsigned(0x10) byte data 6. bit 5 normal(0x00)/page '0'(0x20) reference 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference - 8. bit 7 LSB byte(0x00)/MSB byte(0x80) with 2-byte - mode + 8. bit 7 LSB byte(0x00)/MSB byte(0x80) with 2-byte + mode + 9. bit 8 1 or 2 (0x00)/3-byte (0x100) object format + for byte data. + 10. bit 9 LSB or MSB (middle byte) (0x00) or byte 3 + (real MSB) (0x200) for 3-byte mode. + + If the upper four bits of n1 are set (i.e. + (n1 & 0xf0) == 0xf0), it is taken as an escape character, + and the relocation mode will consist of the lower four bits + of n1 left shifted 8 bits or'ed with the value of n1x. If + the upper four bits of n1 are not all set, then it is not an + escape character, and the n1x byte is not present. + + This escape mechanism allows a 12-bit relocation mode value. + + Note that in byte mode, when 3-byte mode is used (bits 0 + and 8 are both set), the MSB bit (bit 7) really refers to + the 16 bit MSB (the middle byte of the 24-bit value) while + the "byte 3" bit (bit 9) refers to the 24-bit MSB. 2. n2 is a byte index into the corresponding (i.e. pre- ceeding) T line data (i.e. a pointer to the data to be diff --git a/as/mcs51/asexpr.c b/as/mcs51/asexpr.c index 1a94aa64..e675be35 100644 --- a/as/mcs51/asexpr.c +++ b/as/mcs51/asexpr.c @@ -199,6 +199,23 @@ int n; esp->e_rlcf |= R_MSB ; break; } + else if (esp->e_base.e_ap && re.e_addr == 16) + { + if (flat24Mode) + { + esp->e_rlcf |= R_HIB; + } + else + { + warnBanner(); + fprintf(stderr, + "(expr >> 16) is only meaningful in " + ".flat24 mode.\n"); + qerr(); + } + + break; + } /* else continue with the normal processing */ abscheck(esp); esp->e_addr >>= re.e_addr; diff --git a/as/mcs51/aslink.h b/as/mcs51/aslink.h index 2fd486ea..b0c9a969 100644 --- a/as/mcs51/aslink.h +++ b/as/mcs51/aslink.h @@ -107,30 +107,36 @@ * +-----+-----+-----+-----+-----+-----+-----+-----+ */ -#define R_WORD 0000 /* 16 bit */ -#define R_BYTE 0001 /* 8 bit */ +#define R_WORD 0x00 /* 16 bit */ +#define R_BYTE 0x01 /* 8 bit */ -#define R_AREA 0000 /* Base type */ -#define R_SYM 0002 +#define R_AREA 0x00 /* Base type */ +#define R_SYM 0x02 -#define R_NORM 0000 /* PC adjust */ -#define R_PCR 0004 +#define R_NORM 0x00 /* PC adjust */ +#define R_PCR 0x04 -#define R_BYT1 0000 /* Byte count for R_BYTE = 1 */ -#define R_BYT2 0010 /* Byte count for R_BYTE = 2 */ +#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */ +#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */ -#define R_SGND 0000 /* Signed value */ -#define R_USGN 0020 /* Unsigned value */ +#define R_SGND 0x00 /* Signed Byte */ +#define R_USGN 0x10 /* Unsigned Byte */ -#define R_NOPAG 0000 /* Page Mode */ -#define R_PAG0 0040 /* Page '0' */ -#define R_PAG 0100 /* Page 'nnn' */ +#define R_NOPAG 0x00 /* Page Mode */ +#define R_PAG0 0x20 /* Page '0' */ +#define R_PAG 0x40 /* Page 'nnn' */ -/* - * Valid for R_BYT2: - */ -#define R_LSB 0000 /* output low byte */ -#define R_MSB 0200 /* output high byte */ +#define R_LSB 0x00 /* low byte */ +#define R_MSB 0x80 /* high byte */ + +#define R_BYT3 0x100 /* if R_BYTE is set, this is a + * 3 byte address, of which + * the linker must select one byte. + */ +#define R_HIB 0x200 /* If R_BYTE & R_BYT3 are set, linker + * will select byte 3 of the relocated + * 24 bit address. + */ #define R_J11 (R_WORD|R_BYT2) /* JLH: 11 bit JMP and CALL (8051) */ #define R_J19 (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */ @@ -141,6 +147,11 @@ #define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11) #define IS_C24(x) (((x) & R_J19_MASK) == R_C24) +#define R_ESCAPE_MASK 0xf0 /* Used to escape relocation modes + * greater than 0xff in the .rel + * file. + */ + /* * Global symbol types. */ @@ -685,6 +696,9 @@ extern VOID slew(); extern addr_t adb_b(); extern addr_t adb_hi(); extern addr_t adb_lo(); +extern addr_t adb_24_hi(addr_t v, int i); +extern addr_t adb_24_mid(addr_t v, int i); +extern addr_t adb_24_lo(addr_t v, int i); extern addr_t adw_w(); extern addr_t adw_24(addr_t, int); extern addr_t adw_hi(); diff --git a/as/mcs51/asm.h b/as/mcs51/asm.h index 61c96daa..a7a8131a 100644 --- a/as/mcs51/asm.h +++ b/as/mcs51/asm.h @@ -172,27 +172,36 @@ struct area * +-----+-----+-----+-----+-----+-----+-----+-----+ */ -#define R_WORD 0000 /* 16 bit */ -#define R_BYTE 0001 /* 8 bit */ +#define R_WORD 0x00 /* 16 bit */ +#define R_BYTE 0x01 /* 8 bit */ -#define R_AREA 0000 /* Base type */ -#define R_SYM 0002 +#define R_AREA 0x00 /* Base type */ +#define R_SYM 0x02 -#define R_NORM 0000 /* PC adjust */ -#define R_PCR 0004 +#define R_NORM 0x00 /* PC adjust */ +#define R_PCR 0x04 -#define R_BYT1 0000 /* Byte count for R_BYTE = 1 */ -#define R_BYT2 0010 /* Byte count for R_BYTE = 2 */ +#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */ +#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */ -#define R_SGND 0000 /* Signed Byte */ -#define R_USGN 0020 /* Unsigned Byte */ +#define R_SGND 0x00 /* Signed Byte */ +#define R_USGN 0x10 /* Unsigned Byte */ -#define R_NOPAG 0000 /* Page Mode */ -#define R_PAG0 0040 /* Page '0' */ -#define R_PAG 0100 /* Page 'nnn' */ +#define R_NOPAG 0x00 /* Page Mode */ +#define R_PAG0 0x20 /* Page '0' */ +#define R_PAG 0x40 /* Page 'nnn' */ -#define R_LSB 0000 /* low byte */ -#define R_MSB 0200 /* high byte */ +#define R_LSB 0x00 /* low byte */ +#define R_MSB 0x80 /* high byte */ + +#define R_BYT3 0x100 /* if R_BYTE is set, this is a + * 3 byte address, of which + * the linker must select one byte. + */ +#define R_HIB 0x200 /* If R_BYTE & R_BYT3 are set, linker + * will select byte 3 of the relocated + * 24 bit address. + */ #define R_J11 (R_WORD|R_BYT2) /* JLH: 11 bit JMP and CALL (8051) */ #define R_J19 (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */ @@ -203,6 +212,11 @@ struct area #define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11) #define IS_C24(x) (((x) & R_J19_MASK) == R_C24) +#define R_ESCAPE_MASK 0xf0 /* Used to escape relocation modes + * greater than 0xff in the .rel + * file. + */ + /* * Listing Control Flags */ @@ -518,7 +532,7 @@ struct expr struct area *e_ap; struct sym *e_sp; } e_base; /* Rel. base */ - char e_rlcf; /* Rel. flags */ + int e_rlcf; /* Rel. flags */ }; /* C Library functions */ @@ -613,7 +627,7 @@ extern VOID outbuf(); extern VOID outchk(); extern VOID outgsd(); extern VOID outrb(); -extern VOID outrw(); +extern VOID outrw(struct expr *, int); extern VOID outr24(struct expr *, int); extern VOID outsym(); extern VOID out_lb(); diff --git a/as/mcs51/asout.c b/as/mcs51/asout.c index d107854d..90a80afa 100644 --- a/as/mcs51/asout.c +++ b/as/mcs51/asout.c @@ -279,6 +279,51 @@ outaw(w) dot.s_addr += 2; } +/*)Function VOID write_rmode(r) + * + * int r relocation mode + * + * write_rmode puts the passed relocation mode into the + * output relp buffer, escaping it if necessary. + * + * global variables: + * int * relp pointer to rel array + * + * functions called: + * VOID rerr() assubr.c + * + * side effects: + * relp is incremented appropriately. + */ +VOID +write_rmode(int r) +{ + /* We need to escape the relocation mode if it is greater + * than a byte, or if it happens to look like an escape. + * (I don't think that the latter case is legal, but + * better safe than sorry). + */ + if ((r > 0xff) || ((r & R_ESCAPE_MASK) == R_ESCAPE_MASK)) + { + /* Hack in up to an extra 4 bits of flags with escape. */ + if (r > 0xfff) + { + /* uh-oh.. we have more than 4 extra bits. */ + fprintf(stderr, + "Internal error: relocation mode 0x%X too big.\n", + r); + rerr(); + } + /* printf("escaping relocation mode\n"); */ + *relp++ = R_ESCAPE_MASK | (r >> 8); + *relp++ = r & 0xff; + } + else + { + *relp++ = r; + } +} + /*)Function VOID outrb(esp, r) * * expr * esp pointer to expr structure @@ -312,28 +357,43 @@ outaw(w) */ VOID -outrb(esp, r) -register struct expr *esp; -int r; +outrb(struct expr *esp, int r) { register int n; if (pass == 2) { if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { + /* This is a constant; simply write the + * const byte to the T line and don't + * generate any relocation info. + */ out_lb(lobyte(esp->e_addr),0); if (oflag) { outchk(1, 0); *txtp++ = lobyte(esp->e_addr); } } else { - r |= R_BYTE | R_BYT2 | esp->e_rlcf; - if (r & R_MSB) { + /* We are generating a single byte of relocatable + * info. + * + * In 8051 mode, we generate a 16 bit address. The + * linker will later select a single byte based on + * whether R_MSB is set. + * + * In flat24 mode, we generate a 24 bit address. The + * linker will select a single byte based on + * whether R_MSB or R_HIB is set. + */ + if (!flat24Mode) + { + r |= R_BYTE | R_BYT2 | esp->e_rlcf; + if (r & R_MSB) { out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH); - } else { + } else { out_lb(lobyte(esp->e_addr),r|R_RELOC); - } - if (oflag) { - outchk(2, 4); + } + if (oflag) { + outchk(2, 5); out_tw(esp->e_addr); if (esp->e_flag) { n = esp->e_base.e_sp->s_ref; @@ -341,9 +401,40 @@ int r; } else { n = esp->e_base.e_ap->a_ref; } - *relp++ = r; + write_rmode(r); *relp++ = txtp - txt - 2; out_rw(n); + } + } + else + { + /* 24 bit mode. */ + r |= R_BYTE | R_BYT3 | esp->e_rlcf; + if (r & R_HIB) + { + /* Probably should mark this differently in the + * listing file. + */ + out_lb(byte3(esp->e_addr),r|R_RELOC|R_HIGH); + } + else if (r & R_MSB) { + out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH); + } else { + out_lb(lobyte(esp->e_addr),r|R_RELOC); + } + if (oflag) { + outchk(3, 5); + out_t24(esp->e_addr); + if (esp->e_flag) { + n = esp->e_base.e_sp->s_ref; + r |= R_SYM; + } else { + n = esp->e_base.e_ap->a_ref; + } + write_rmode(r); + *relp++ = txtp - txt - 3; + out_rw(n); + } } } } @@ -383,9 +474,7 @@ int r; */ VOID -outrw(esp, r) -register struct expr *esp; -int r; +outrw(struct expr *esp, int r) { register int n; @@ -417,7 +506,7 @@ int r; out_lw(esp->e_addr,r|R_RELOC); } if (oflag) { - outchk(2, 4); + outchk(2, 5); out_tw(esp->e_addr); if (esp->e_flag) { n = esp->e_base.e_sp->s_ref; @@ -437,7 +526,7 @@ int r; "outrw()\n"); rerr(); } - *relp++ = r; + write_rmode(r); *relp++ = txtp - txt - 2; out_rw(n); } @@ -506,7 +595,7 @@ outr24(struct expr *esp, int r) out_l24(esp->e_addr,r|R_RELOC); } if (oflag) { - outchk(3, 4); + outchk(3, 5); out_t24(esp->e_addr); if (esp->e_flag) { n = esp->e_base.e_sp->s_ref; @@ -529,7 +618,7 @@ outr24(struct expr *esp, int r) rerr(); } - *relp++ = r | R_C24; + write_rmode(r | R_C24); *relp++ = txtp - txt - 3; out_rw(n); } @@ -586,7 +675,7 @@ register struct expr *esp; } else { n = esp->e_base.e_ap->a_ref; } - *relp++ = r; + write_rmode(r); *relp++ = txtp - txt - 2; out_rw(n); } @@ -693,7 +782,7 @@ outchk(nt, nr) if (txtp == txt) { out_tw(dot.s_addr); if ((ap = dot.s_area) != NULL) { - *relp++ = R_WORD|R_AREA; + write_rmode(R_WORD|R_AREA); *relp++ = 0; out_rw(ap->a_ref); } @@ -989,19 +1078,17 @@ register struct sym *sp; */ VOID -out(p, n) -register char *p; -register int n; +out(char *p, int n) { while (n--) { if (xflag == 0) { - fprintf(ofp, " %02X", (*p++)&0377); + fprintf(ofp, " %02X", (*p++)&0xff); } else if (xflag == 1) { - fprintf(ofp, " %03o", (*p++)&0377); + fprintf(ofp, " %03o", (*p++)&0xff); } else if (xflag == 2) { - fprintf(ofp, " %03u", (*p++)&0377); + fprintf(ofp, " %03u", (*p++)&0xff); } } } @@ -1321,7 +1408,7 @@ int r; r |= R_WORD | esp->e_rlcf; out_lw(esp->e_addr,r|R_RELOC); if (oflag) { - outchk(3, 4); + outchk(3, 5); out_tw(esp->e_addr); *txtp++ = op; @@ -1331,7 +1418,7 @@ int r; } else { n = esp->e_base.e_ap->a_ref; } - *relp++ = r; + write_rmode(r); *relp++ = txtp - txt - 3; out_rw(n); } @@ -1366,7 +1453,7 @@ outr19(struct expr * esp, int op, int r) r |= R_WORD | esp->e_rlcf; out_l24(esp->e_addr,r|R_RELOC); if (oflag) { - outchk(4, 4); + outchk(4, 5); out_t24(esp->e_addr); *txtp++ = op; @@ -1376,7 +1463,7 @@ outr19(struct expr * esp, int op, int r) } else { n = esp->e_base.e_ap->a_ref; } - *relp++ = r; + write_rmode(r); *relp++ = txtp - txt - 4; out_rw(n); } diff --git a/as/mcs51/lkrloc.c b/as/mcs51/lkrloc.c index 88cc1438..b102545d 100644 --- a/as/mcs51/lkrloc.c +++ b/as/mcs51/lkrloc.c @@ -306,6 +306,13 @@ relr() while (more()) { error = 0; mode = eval(); + + if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK) + { + mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval(); + /* printf("unescaping rmode\n"); */ + } + rtp = eval(); rindex = evword(); @@ -342,7 +349,7 @@ relr() /* * R_PAG0 or R_PAG addressing */ - if (mode & (R_PAG0|R_PAG)) { + if (mode & (R_PAG0 | R_PAG)) { paga = sdp.s_area->a_addr; pags = sdp.s_addr; reli -= paga + pags; @@ -352,7 +359,38 @@ relr() * R_BYTE or R_WORD operation */ if (mode & R_BYTE) { - if (mode & R_BYT2) { + if (mode & R_BYT3) + { + /* This is a three byte address, of which + * we will select one byte. + */ + if (mode & R_HIB) + { + /* printf("24 bit address selecting hi byte.\n"); */ + relv = adb_24_hi(reli, rtp); + } + else if (mode & R_MSB) + { + /* Note that in 24 bit mode, R_MSB + * is really the middle byte, not + * the most significant byte. + * + * This is ugly and I can only apologize + * for any confusion. + */ + /* printf("24 bit address selecting middle byte.\n"); */ + relv = adb_24_mid(reli, rtp); + } + else + { + /* printf("24 bit address selecting lo byte.\n"); */ + relv = adb_24_lo(reli, rtp); + } + } + else if (mode & R_BYT2) { + /* This is a two byte address, of + * which we will select one byte. + */ if (mode & R_MSB) { relv = adb_hi(reli, rtp); } else { @@ -857,6 +895,143 @@ int i; return (j); } +/*)Function addr_t adb_24_hi(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_hi() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The LSB & middle byte rtflg[] is cleared. + * + * local variable: + * addr_t j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * LSB & middle byte of the word value is cleared to + * reflect the fact that the MSB is the selected byte. + * + */ + +addr_t +adb_24_hi(addr_t v, int i) +{ + register addr_t j; + + j = adw_24(v, i); + + /* Remove the lower two bytes. */ + if (hilo) + { + rtflg[i+2] = 0; + } + else + { + rtflg[i] = 0; + } + rtflg[i+1] = 0; + + return (j); +} + +/*)Function addr_t adb_24_mid(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_mid() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The LSB & MSB byte rtflg[] is cleared. + * + * local variable: + * addr_t j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * LSB & MSB of the 24 bit value is cleared to reflect + * the fact that the middle byte is the selected byte. + * + */ + +addr_t +adb_24_mid(addr_t v, int i) +{ + register addr_t j; + + j = adw_24(v, i); + + /* remove the MSB & LSB. */ + rtflg[i+2] = 0; + rtflg[i] = 0; + + return (j); +} + +/*)Function addr_t adb_24_lo(v, i) + * + * int v value to add to byte + * int i rtval[] index + * + * The function adb_24_lo() adds the value of v to the + * 24 bit value contained in rtval[i] - rtval[i+2]. + * The new value of rtval[i] / rtval[i+1] is returned. + * The MSB & middle byte rtflg[] is cleared. + * + * local variable: + * addr_t j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The value of rtval[] is changed. + * The rtflg[] value corresponding to the + * MSB & middle byte of the word value is cleared to + * reflect the fact that the LSB is the selected byte. + * + */ + +addr_t +adb_24_lo(addr_t v, int i) +{ + register addr_t j; + + j = adw_24(v, i); + + /* Remove the upper two bytes. */ + if (hilo) + { + rtflg[i] = 0; + } + else + { + rtflg[i+2] = 0; + } + rtflg[i+1] = 0; + + return (j); +} + /*)Function addr_t adw_w(v, i) * * int v value to add to word