From: kvigor Date: Sun, 6 Feb 2000 20:29:41 +0000 (+0000) Subject: Add 24 bit flat mode support for DS80C390 to assembler and linker X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=554b80355adbbbd8436bdb0dd448ef3e956c0871;p=fw%2Fsdcc Add 24 bit flat mode support for DS80C390 to assembler and linker git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@71 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/as/mcs51/asdata.c b/as/mcs51/asdata.c index 0ae83f37..f1abb1eb 100644 --- a/as/mcs51/asdata.c +++ b/as/mcs51/asdata.c @@ -130,6 +130,9 @@ char tb[NTITL]; /* Title string buffer */ char stb[NSBTL]; /* Subtitle string buffer */ +int flat24Mode; /* non-zero if we are using DS390 24 bit + * flat mode (via .flat24 directive). + */ char symtbl[] = { "Symbol Table" }; char aretbl[] = { "Area Table" }; diff --git a/as/mcs51/aslink.h b/as/mcs51/aslink.h index 77f84c82..2fd486ea 100644 --- a/as/mcs51/aslink.h +++ b/as/mcs51/aslink.h @@ -133,6 +133,13 @@ #define R_MSB 0200 /* output high byte */ #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) */ +#define R_C24 (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */ +#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB) + +#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19) +#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11) +#define IS_C24(x) (((x) & R_J19_MASK) == R_C24) /* * Global symbol types. @@ -548,6 +555,8 @@ extern int pflag; /* print linker command file flag */ extern int uflag; /* Listing relocation flag */ +extern int rflag; /* Extended linear address record flag. + */ extern int radix; /* current number conversion radix: * 2 (binary), 8 (octal), 10 (decimal), * 16 (hexadecimal) @@ -677,6 +686,7 @@ extern addr_t adb_b(); extern addr_t adb_hi(); extern addr_t adb_lo(); extern addr_t adw_w(); +extern addr_t adw_24(addr_t, int); extern addr_t adw_hi(); extern addr_t adw_lo(); extern addr_t evword(); @@ -691,6 +701,7 @@ extern VOID errdmp(); extern VOID relerp(); extern VOID erpdmp(); extern VOID prntval(); +extern int lastExtendedAddress; /* lklibr.c */ extern VOID addfile(); @@ -706,7 +717,7 @@ extern VOID s19(); /* lkihx.c */ extern VOID ihx(); - +extern VOID ihxEntendedLinearAddress(addr_t); /* lkstore.c */ extern char *StoreString( char *str ); @@ -716,3 +727,4 @@ extern void DefineNoICE( char *name, addr_t value, int page ); /* SD added this to change strcmpi --> strcmp (strcmpi NOT ANSI) */ #define strcmpi strcmp + diff --git a/as/mcs51/asm.h b/as/mcs51/asm.h index e0229054..61c96daa 100644 --- a/as/mcs51/asm.h +++ b/as/mcs51/asm.h @@ -22,9 +22,12 @@ * - prototypes for DefineNoICE_Line * 30-Jan-98 JLH: * - add memory space flags to a_flag for 8051 + * + * 3-Feb-00 KV: + * - add DS80C390 flat mode support. */ -#define VERSION "V01.70 + NoICE + SDCC mods Feb-1999" +#define VERSION "V01.70 + NoICE + SDCC mods + Flat24 Feb-1999" /* * Case Sensitivity Flag @@ -101,6 +104,10 @@ #define dca area[0] /* Dca, default code area */ +/* NB: for Flat24 extentions to work, addr_t must be at least 24 + * bits. This is checked at runtime when the .flat24 directive + * is processed. + */ typedef unsigned int addr_t; /* @@ -188,6 +195,13 @@ struct area #define R_MSB 0200 /* high byte */ #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) */ +#define R_C24 (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */ +#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB) + +#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19) +#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11) +#define IS_C24(x) (((x) & R_J19_MASK) == R_C24) /* * Listing Control Flags @@ -283,6 +297,7 @@ struct sym #define S_ORG 24 /* .org */ #define S_MODUL 25 /* .module */ #define S_ASCIS 26 /* .ascis */ +#define S_FLAT24 27 /* .flat24 */ /* @@ -433,6 +448,9 @@ extern char tb[NTITL]; /* Title string buffer */ extern char stb[NSBTL]; /* Subtitle string buffer */ +extern int flat24Mode; /* non-zero if we are using DS390 24 bit + * flat mode (via .flat24 directive). + */ extern char symtbl[]; /* string "Symbol Table" */ extern char aretbl[]; /* string "Area Table" @@ -559,6 +577,7 @@ extern VOID allglob(); extern VOID aerr(); extern VOID diag(); extern VOID err(); +extern VOID warnBanner(void); extern char * geterr(); extern VOID qerr(); extern VOID rerr(); @@ -583,6 +602,7 @@ extern VOID slew(); /* asout.c */ extern int hibyte(); extern int lobyte(); +extern int byte3(int); extern VOID out(); extern VOID outab(); extern VOID outarea(); @@ -594,12 +614,16 @@ extern VOID outchk(); extern VOID outgsd(); extern VOID outrb(); extern VOID outrw(); +extern VOID outr24(struct expr *, int); extern VOID outsym(); extern VOID out_lb(); extern VOID out_lw(); +extern VOID out_l24(int, int); extern VOID out_rw(); extern VOID out_tw(); +extern VOID out_t24(int); extern VOID outr11(); /* JLH */ +extern VOID outr19(struct expr *, int, int); /* asstore.c */ extern char *StoreString( char *str ); diff --git a/as/mcs51/asmain.c b/as/mcs51/asmain.c index 854d0437..42c70a5d 100644 --- a/as/mcs51/asmain.c +++ b/as/mcs51/asmain.c @@ -917,6 +917,50 @@ loop: } lmode = SLIST; break; + + case S_FLAT24: + if (more()) + { + getst(id, -1); + + if (!strcmpi(id, "on")) + { + /* Quick sanity check: size of + * addr_t must be at least 24 bits. + */ + if (sizeof(addr_t) < 3) + { + warnBanner(); + fprintf(stderr, + "Cannot enable Flat24 mode: " + "host system must have 24 bit " + "or greater integers.\n"); + } + else + { + flat24Mode = 1; + } + } + else if (!strcmpi(id, "off")) + { + flat24Mode = 0; + } + else + { + qerr(); + } + } + else + { + qerr(); + } + lmode = SLIST; + #if 0 + printf("as8051: ds390 flat mode %sabled.\n", + flat24Mode ? "en" : "dis"); + #endif + break; + /* * If not an assembler directive then go to diff --git a/as/mcs51/asout.c b/as/mcs51/asout.c index b581ca3a..d107854d 100644 --- a/as/mcs51/asout.c +++ b/as/mcs51/asout.c @@ -390,6 +390,14 @@ int r; register int n; if (pass == 2) { + + if (esp->e_addr > 0xffff) + { + warnBanner(); + fprintf(stderr, + "large constant 0x%x truncated to 16 bits\n", + esp->e_addr); + } if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { out_lw(esp->e_addr,0); if (oflag) { @@ -417,6 +425,18 @@ int r; } else { n = esp->e_base.e_ap->a_ref; } + + if (IS_C24(r)) + { + /* If this happens, the linker will + * attempt to process this 16 bit field + * as 24 bits. That would be bad. + */ + fprintf(stderr, + "***Internal error: C24 out in " + "outrw()\n"); + rerr(); + } *relp++ = r; *relp++ = txtp - txt - 2; out_rw(n); @@ -426,6 +446,98 @@ int r; dot.s_addr += 2; } +/*)Function VOID outr24(esp, r) + * + * expr * esp pointer to expr structure + * int r relocation mode + * + * The function outr24() processes 24 bits of generated code + * in either absolute or relocatable format dependent upon + * the data contained in the expr structure esp. If the + * .REL output is enabled then the appropriate information + * is loaded into the txt and rel buffers. + * + * local variables: + * int n symbol/area reference number + * int * relp pointer to rel array + * int * txtp pointer to txt array + * + * global variables: + * sym dot defined as sym[0] + * int oflag -o, generate relocatable output flag + * int pass assembler pass number + * + * functions called: + * VOID aerr() assubr.c + * VOID outchk() asout.c + * VOID out_l24() asout.c + * VOID out_rw() asout.c + * VOID out_t24() asout.c + * + * side effects: + * The current assembly address is incremented by 3. + */ + +VOID +outr24(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 expression. */ + out_l24(esp->e_addr,0); + if (oflag) { + outchk(3, 0); + out_t24(esp->e_addr); + } + } else { + /* This is a symbol. */ + r |= R_WORD | esp->e_rlcf; + if (r & R_BYT2) { + /* I have no idea what this case is. */ + rerr(); + if (r & R_MSB) { + out_lw(hibyte(esp->e_addr),r|R_RELOC); + } else { + out_lw(lobyte(esp->e_addr),r|R_RELOC); + } + } else { + out_l24(esp->e_addr,r|R_RELOC); + } + if (oflag) { + outchk(3, 4); + 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; + } + + if (r & R_BYTE) + { + /* If this occurs, we cannot properly + * code the relocation data with the + * R_C24 flag. This means the linker + * will fail to do the 24 bit relocation. + * Which will suck. + */ + fprintf(stderr, + "***Internal error: BYTE out in 24 " + "bit flat mode unexpected.\n"); + rerr(); + } + + *relp++ = r | R_C24; + *relp++ = txtp - txt - 3; + out_rw(n); + } + } + } + dot.s_addr += 3; +} + /*)Function VOID outdp(carea, esp) * * area * carea pointer to current area strcuture @@ -963,6 +1075,43 @@ register int n,t; } } +/*)Function VOID out_l24(n, t) + * + * int n assembled data + * int t relocation type + * + * The function out_l24() copies the assembled data and + * its relocation type to the list data buffers. + * + * local variables: + * none + * + * global variables: + * int * cp pointer to assembler output array cb[] + * int * cpt pointer to assembler relocation type + * output array cbt[] + * + * functions called: + * none + * + * side effects: + * Pointers to data and relocation buffers incremented by 3. + */ + +VOID +out_l24(int n, int t) +{ + if (hilo) { + out_lb(byte3(n),t ? t|R_HIGH : 0); + out_lb(hibyte(n),t); + out_lb(lobyte(n),t); + } else { + out_lb(lobyte(n),t); + out_lb(hibyte(n),t); + out_lb(byte3(n),t ? t|R_HIGH : 0); + } +} + /*)Function VOID out_rw(n) * * int n data word @@ -1031,6 +1180,41 @@ register int n; } } +/*)Function VOID out_t24(n) + * + * int n data word + * + * The function out_t24() outputs the text (T) + * data word as three bytes ordered according to hilo. + * + * local variables: + * int * txtp pointer to txt array + * + * global variables: + * none + * + * functions called: + * int lobyte() asout.c + * int hibyte() asout.c + * + * side effects: + * Pointer to relocation buffer incremented by 3. + */ + +VOID +out_t24(int n) +{ + if (hilo) { + *txtp++ = byte3(n); + *txtp++ = hibyte(n); + *txtp++ = lobyte(n); + } else { + *txtp++ = lobyte(n); + *txtp++ = hibyte(n); + *txtp++ = byte3(n); + } +} + /*)Function int lobyte(n) * * int n data word @@ -1083,6 +1267,31 @@ hibyte(n) return ((n>>8)&0377); } +/*)Function int byte3(n) + * + * int n 24 bit data + * + * The function byte3() returns the MSB of the + * 24 bit integer n. + * + * local variables: + * none + * + * global variables: + * none + * + * functions called: + * none + * + * side effects: + * none + */ +int +byte3(int n) +{ + return ((n >> 16) & 0xff); +} + /* * JLH: Output relocatable 11 bit jump/call * @@ -1129,3 +1338,48 @@ int r; } dot.s_addr += 2; } + +/* + * Output relocatable 19 bit jump/call + * + * This function is derived from outrw(), adding the parameter for the + * 19 bit address. This form of address is used only in the DS80C390 + * Flat24 mode. + */ +VOID +outr19(struct expr * esp, int op, int r) +{ + register int n; + + if (pass == 2) { + if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { + /* equated absolute destination. Assume value + * relative to current area */ + esp->e_base.e_ap = dot.s_area; + } + + /* Relocatable destination. Build FOUR + * byte output: relocatable 24-bit entity, followed + * by op-code. Linker will combine them. + * Listing shows only the address. + */ + r |= R_WORD | esp->e_rlcf; + out_l24(esp->e_addr,r|R_RELOC); + if (oflag) { + outchk(4, 4); + out_t24(esp->e_addr); + *txtp++ = op; + + if (esp->e_flag) { + n = esp->e_base.e_sp->s_ref; + r |= R_SYM; + } else { + n = esp->e_base.e_ap->a_ref; + } + *relp++ = r; + *relp++ = txtp - txt - 4; + out_rw(n); + } + } + dot.s_addr += 3; +} diff --git a/as/mcs51/assubr.c b/as/mcs51/assubr.c index d276061f..a5026e74 100644 --- a/as/mcs51/assubr.c +++ b/as/mcs51/assubr.c @@ -127,6 +127,48 @@ diag() } } +/*)Function VOID warnBanner() + * + * The function warnBanner() prints a generic warning message + * header (including the current source file/line) and positions + * the output for a more specific warning message. + * + * It is assumed that the call to warnBanner will be followed with + * a fprintf to stderr (or equivalent) with the specific warning + * text. + * + * local variables: + * none + * + * global variables: + * int cfile current source file index + * int incfile current include file index + * char incfn[] array of include file names + * int incline[] array of include line numbers + * char srcfn[] array of source file names + * int srcline[] array of source line numbers + * FILE * stderr c_library + * + * functions called: + * int fprintf() c_library + * + * side effects: + * none + */ +VOID +warnBanner(void) +{ + fprintf(stderr, "?ASxxxx-Warning in line "); + if (incfil >= 0) { + fprintf(stderr, "%d", incline[incfil]); + fprintf(stderr, " of %s\n", incfn[incfil]); + } else { + fprintf(stderr, "%d", srcline[cfile]); + fprintf(stderr, " of %s\n", srcfn[cfile]); + } + fprintf(stderr, " "); +} + /*)Functions: VOID aerr() * VOID qerr() * VOID rerr() diff --git a/as/mcs51/i51mch.c b/as/mcs51/i51mch.c index e90d01a7..e15266f4 100644 --- a/as/mcs51/i51mch.c +++ b/as/mcs51/i51mch.c @@ -39,17 +39,39 @@ struct mne *mp; break; case S_JMP11: - /* 11 bit destination. Top 3 bits become the MSBs of - / the op-code. + /* ACALL or AJMP. In Flat24 mode, this is a + * 19 bit destination; in 8051 mode, this is a + * 11 bit destination. + * + * The opcode is merged with the address in a + * hack-o-matic fashion by the linker. */ expr(&e, 0); + if (flat24Mode) + { + outr19(&e, op, R_J19); + } + else + { outr11(&e, op, R_J11); + } break; case S_JMP16: + /* LCALl or LJMP. In Flat24 mode, this is a 24 bit + * destination; in 8051 mode, this is a 16 bit + * destination. + */ expr(&e, 0); outab(op); + if (flat24Mode) + { + outr24(&e, 0); + } + else + { outrw(&e, 0); + } break; case S_ACC: @@ -367,7 +389,19 @@ struct mne *mp; if (t1 != S_IMMED) aerr(); outab(0x90); + + /* mov DPTR, #immed: for Flat24 mode, + * #immed is a 24 bit constant. For 8051, + * it is a 16 bit constant. + */ + if (flat24Mode) + { + outr24(&e1, 0); + } + else + { outrw(&e1, 0); + } break; default: diff --git a/as/mcs51/i51pst.c b/as/mcs51/i51pst.c index f084ca60..4fcd97ae 100644 --- a/as/mcs51/i51pst.c +++ b/as/mcs51/i51pst.c @@ -59,6 +59,7 @@ struct mne mne[] = { { NULL, ".org", S_ORG, 0, 0}, { NULL, ".module", S_MODUL, 0, 0}, { NULL, ".ascis", S_ASCIS, 0, 0}, + { NULL, ".flat24", S_FLAT24, 0, 0}, /* 8051 */ diff --git a/as/mcs51/lkdata.c b/as/mcs51/lkdata.c index 87a51e7e..97a2e847 100644 --- a/as/mcs51/lkdata.c +++ b/as/mcs51/lkdata.c @@ -59,6 +59,8 @@ int pflag; /* print linker command file flag */ int uflag; /* Listing relocation flag */ +int rflag; /* Extended linear address record flag. + */ int radix; /* current number conversion radix: * 2 (binary), 8 (octal), 10 (decimal), * 16 (hexadecimal) diff --git a/as/mcs51/lkihx.c b/as/mcs51/lkihx.c index d849c165..77d7b9ac 100644 --- a/as/mcs51/lkihx.c +++ b/as/mcs51/lkihx.c @@ -132,3 +132,36 @@ ihx(i) fprintf(ofp, ":00000001FF\n"); } } + +/*)Function ihxEntendedLinearAddress(i) + * + * addr_t i 16 bit extended linear address. + * + * The function ihxEntendedLinearAddress() writes an extended + * linear address record (type 04) to the output file. + * + * local variables: + * addr_t chksum byte checksum + * + * global variables: + * FILE * ofp output file handle + * + * functions called: + * int fprintf() c_library + * + * side effects: + * The data is output to the file defined by ofp. + */ +VOID +ihxEntendedLinearAddress(addr_t a) +{ + addr_t chksum; + + /* The checksum is the complement of the bytes in the + * record: the 2 is record length, 4 is the extended linear + * address record type, plus the two address bytes. + */ + chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff); + + fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (-chksum) & 0xff); +} \ No newline at end of file diff --git a/as/mcs51/lkmain.c b/as/mcs51/lkmain.c index a439cbb1..21ae1661 100644 --- a/as/mcs51/lkmain.c +++ b/as/mcs51/lkmain.c @@ -412,6 +412,7 @@ link() sdp.s_area = NULL; sdp.s_areax = NULL; sdp.s_addr = 0; + lastExtendedAddress = -1; break; case 'M': @@ -680,7 +681,10 @@ parse() case 'U': uflag = 1; break; - + case 'r': + case 'R': + rflag = 1; + break; case 'x': case 'X': xflag = 0; diff --git a/as/mcs51/lkrloc.c b/as/mcs51/lkrloc.c index 37af57a2..88cc1438 100644 --- a/as/mcs51/lkrloc.c +++ b/as/mcs51/lkrloc.c @@ -47,6 +47,11 @@ * */ +/* Global which holds the upper 16 bits of the last 32 bit area adress + * output. Useful only for iHex mode. + */ +int lastExtendedAddress; + /*)Function VOID reloc(c) * * char c process code @@ -291,6 +296,10 @@ relr() */ pc = adw_w(a[aindex]->a_addr, 0); + #if 0 + printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, + a[aindex]->a_addr, a[aindex]->a_size, rtbase); + #endif /* * Do remaining relocations */ @@ -352,7 +361,7 @@ relr() } else { relv = adb_b(reli, rtp); } - } else if (mode & R_J11) { + } else if (IS_R_J11(mode)) { /* JLH: 11 bit jump destination for 8051. Forms / two byte instruction with op-code bits / in the MIDDLE! @@ -376,27 +385,41 @@ relr() rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2]; rtflg[rtp+2] = 0; rtofst += 1; - } else { - /* - * R_WORD with the R_BYT2 mode is flagged - * as an 'r' error by the assembler, - * but it is processed here anyway. + } + else if (IS_R_J19(mode)) { + /* 19 bit jump destination for DS80C390. Forms + / three byte instruction with op-code bits + / in the MIDDLE! + / rtp points at 4 byte locus: first three + / will get the instructiion. fourth one + / has raw op-code. */ -#if 0 - /* JLH: R_WORD and R_BYT2 together is now subsumed by R_J11 */ - if (mode & R_BYT2) { - if (mode & R_MSB) { - relv = adw_hi(reli, rtp); - } else { - relv = adw_lo(reli, rtp); + /* Calculate absolute destination + / relv must be on same 512K page as pc + */ + relv = adw_24(reli, rtp); + + if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) { + error = 2; } - } else { - relv = adw_w(reli, rtp); + + /* Merge MSB (byte 0) with op-code, ignoring + / top 5 bits of address. Then hide the op-code + */ + rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3]; + rtflg[rtp+3] = 0; + rtofst += 1; + } + else if (IS_C24(mode)) + { + /* 24 bit address */ + relv = adw_24(reli, rtp); } -#else + else + { + /* 16 bit address. */ relv = adw_w(reli, rtp); -#endif } /* @@ -449,6 +472,50 @@ relr() /* JLH: output only if data (beyond two byte address) */ if ((oflag == 1) && (rtcnt > 2)) { + int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff; + + /* Boy, is this a hack: for ABS sections, the + * base address is stored as zero, and the T records + * indicate the offset from zero. + * + * Since T records can only indicate a 16 bit offset, this + * obviously creates a problem for ABS segments located + * above 64K (this is only meaningful in flat24 mode). + * + * However, the size of an ABS area is stored as + * base address + section size (I suspect this is a bug, + * but it's a handy one right now). So the upper 8 bits of + * the 24 bit address are stored in the size record. + * Thus we add it in. + * + * This is another reason why we can't have areas greater + * than 64K yet, even in flat24 mode. + */ + extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff); + + if (extendedAddress != lastExtendedAddress) + { + + #if 0 + printf("output extended linear address record 0x%x\n", + extendedAddress); + #endif + + if (rflag) + { + ihxEntendedLinearAddress(extendedAddress); + } + else if (extendedAddress) + { + /* Not allowed to generate extended address records, + * but one is called for here... + */ + fprintf(stderr, + "warning: extended linear address encountered; " + "you probably want the -r flag.\n"); + } + lastExtendedAddress = extendedAddress; + } ihx(1); } else if ((oflag == 2) && (rtcnt > 2)) { @@ -832,6 +899,51 @@ register int i; return(j); } +/*)Function addr_t adw_24(v, i) + * + * int v value to add to word + * int i rtval[] index + * + * The function adw_w() 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+2] is returned. + * + * local variable: + * addr_t j temporary evaluation variable + * + * global variables: + * hilo byte ordering parameter + * + * called functions: + * none + * + * side effects: + * The word value of rtval[] is changed. + * + */ +addr_t +adw_24(addr_t v, int i) +{ + register addr_t j; + + if (hilo) { + j = v + ((rtval[i] & 0xff) << 16) + + ((rtval[i+1] & 0xff) << 8) + + (rtval[i+2] & 0xff); + rtval[i] = (j >> 16) & 0xff; + rtval[i+1] = (j >> 8) & 0xff; + rtval[i+2] = j & 0xff; + } else { + j = v + (rtval[i] & 0xff) + + ((rtval[i+1] & 0xff) << 8) + + ((rtval[i+2] & 0xff) << 16); + rtval[i] = j & 0xff; + rtval[i+1] = (j >> 8) & 0xff; + rtval[i+2] = (j >> 16) & 0xff; + } + return(j); +} + /*)Function addr_t adw_lo(v, i) * * int v value to add to byte diff --git a/as/mcs51/readme.390 b/as/mcs51/readme.390 new file mode 100644 index 00000000..80170bd0 --- /dev/null +++ b/as/mcs51/readme.390 @@ -0,0 +1,141 @@ +DS80C390 flat mode support + +2/4/2000 Kevin Vigor (e-mail: kevin at vigor.nu) + +I have hacked the 8051 assembler to support the 24 bit flat address mode of +the DS80C390 processor. This mode allows the chip to directly address up to +4 Meg of RAM. Details can be found at Dallas' web site: www.dalsemi.com. + +1: Assembler changes. + +24 bit mode is entered via a new assembler directive, .flat24. This directive +takes a mandatory argument, which is either the string "on" or the string +"off". ".flat24 on" enables 24-bit mode, and ".flat24 off" puts the assembler +into standard 8051 mode. + +Note that any .included files within a ".flat24 on" segment of the code will +be compiled in 24-bit mode. + +In 24-bit mode, 8 instructions have altered behavior. Of these, 5 modify +the instruction encoding, while 3 differ only in behavior. These +instructions are discussed in the DS80C390 User's Guide, but a summary is +included here: + +ACALL and AJMP now take a 19 bit offset instead of the 8051's 11 bit offset. +An extra address byte is added to the encoded instruction. + +LCALL and LJMP now take a 24 bit target address instead of the 8051's 16 bit +address. An extra address byte is added to the encoded instruction. + +MOV DPTR, #immed now takes a 24 bit immediate value instead of the 8051's 16 +bit address. An extra data byte is added to the encoded instruction. + +INC DPTR now increments the entire 24 bit DPTR. The encoding is not changed. + +RET and RETI restore the full 24 bit PC from the stack. The encoding is not +changed. + +2: Linker changes. + +The linker supports (through a variety of evil hacks) 19 bit ACALL/AJMP +relocations and 24 bit LCALL/LJMP/DPTR relocations. These changes should be +invisible to the user. + +The linker can now also generated extended linear address records in the +Intel hex output format. This is necessary for any areas located above the +64K mark. This is enabled by the "-r" linker flag, and is disabled by +default (but the linker will throw a warning if an extended address is +encountered without the -r flag being enabled). + +Note that for various reasons, areas may still not be larger than 64K. +However, they may be located anywhere in the 4 Meg address space via the +assembler .org directive (for ABS areas) or the linker "-b" option. + +3: Examples + +Note that this example uses ABS areas to make the layout obvious. This code +won't do anything useful at all, but demonstrates the instruction encoding +in .flat24 mode vs 8051 mode. + +; test1.asm +.area CODE (ABS) +.org 0 + +; SFRs not known to the assembler yet... +$TA = 0x00C7 +$ACON = 0x009D + +; Set the chip to 24 bit flat mode via the DS "timed access" procedure. +mov $TA, #0xAA +mov $TA, #0x55 +mov $ACON, #0x06 ; 10 bit stack & 24 bit flat addressing. + +.flat24 on ; Enable 24-bit mode. The AM1 bit had better be + ; on... + +mov dptr, #myData ; Valid on the '390: myData is in the FARDATA + ; area at 0x300001. + ; Generates: 90 30 00 01 +acall _junkNear ; Within 11 bit range, but still must generate + ; 19 bit address for '390 flat mode. + ; Generates: 11 04 00 +ajmp _junkFar ; Within 16 bit range. + ; Generates 01 08 00 +acall _junkReallyFar ; Within 19 bit range. + ; Generates 91 00 00 +lcall _junkReallyReallyFar ; Within 24 bit range. + ; Generates 12 08 00 00 + +; Set the chip to 8051 mode via the DS "timed access" procedure. +mov $TA, #0x0AA +mov $TA, #0x055 +mov $ACON, #0x00 ; 8 bit stack & 16 bit flat addressing. + +.flat24 off ; Now we're an 8051 again. The AM1 bit had better be + ; off... + +;mov dptr, #myData ; Can't do that: myData is too far away. +acall _junkNear ; Within 11 bit range. + ; Generates 91 00 +ljmp _junkFar ; Within 16 bit range; can't AJMP, but can LJMP + ; Generates 02 08 00 +ret + +.area CODE2 (ABS) +.org 0x400 +; This is within the 11 bit ACALL/AJMP range of the 8051. +_junkNear: +ret + +.area CODE3 (ABS) +.org 0x800 +; This is within the 390's 19 bit ACALL/AJMP range, and inside the stock +; 8051's 16 bit LCALL range. +_junkFar: +ret + +.area CODE4 (ABS) +; This is within the 390's 19 bit ACALL/AJMP range and outside the +; 8051's LCALL range. +; Note that to link an image with an area beyond 64K (like this one), +; the '-r' flag must be provided to the linker, and Intel Hex output format +; must be used. +.org 0x40000 +_junkReallyFar: +ret + +.area CODE5 (ABS) +; This is outside anybody's ACALL/AJMP range. +.org 0x80000 +_junkReallyReallyFar: +ret + +.area FARDATA (ABS) +.org 0x300000 +; This is way, way up there. +.byte 0x01 +myData: +.byte 0x02 + +; test1.asm ends. +