Add 24 bit flat mode support for DS80C390 to assembler and linker
authorkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 6 Feb 2000 20:29:41 +0000 (20:29 +0000)
committerkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 6 Feb 2000 20:29:41 +0000 (20:29 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@71 4a8a32a2-be11-0410-ad9d-d568d2c75423

13 files changed:
as/mcs51/asdata.c
as/mcs51/aslink.h
as/mcs51/asm.h
as/mcs51/asmain.c
as/mcs51/asout.c
as/mcs51/assubr.c
as/mcs51/i51mch.c
as/mcs51/i51pst.c
as/mcs51/lkdata.c
as/mcs51/lkihx.c
as/mcs51/lkmain.c
as/mcs51/lkrloc.c
as/mcs51/readme.390 [new file with mode: 0644]

index 0ae83f3721a27afe4de5f17295ec9f4f12097ec6..f1abb1ebd9fc68a67fa12a96ad8214b9d0f0fc8c 100644 (file)
@@ -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" };
index 77f84c8205c67e93c640cc89bf0e93400720ad09..2fd486eaa4e9016ab8f3123d0e1e3bf795f31cc3 100644 (file)
 #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
+
index e02290541db561c7d368be95029e047a455f23c1..61c96daa8f91c754570f91bf8b5ccb21a183c7b3 100644 (file)
  *           - 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
 #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 );
index 854d04371695efa24c4a95e5907bb8473ff5852e..42c70a5d2cd99dc6e664bcd83f68cd02c272c311 100644 (file)
@@ -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
index b581ca3a40f6dd03dbf7fe56a65e264bfca79caa..d107854dbfb95c1576fba60cdc916ae836112c9a 100644 (file)
@@ -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;
+}
index d276061f066690f58ce5dd7df7da0fda13e26f34..a5026e74593b0ef87e0d3010fe3d549811c11cbc 100644 (file)
@@ -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()
index e90d01a7b5a727711a443da8da373030ceb5aa9e..e15266f4c3bf40fa380d127b978ecc009d6f0f87 100644 (file)
@@ -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:
index f084ca60c749debce4101e968b0d5eaf1b4beb08..4fcd97ae8e56d3b0a6fb75fb440a0b7049d41f98 100644 (file)
@@ -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 */
 
index 87a51e7e3bbb4872b73be8de50da617e57da6c76..97a2e8474c6bf948559050d8755c981e4e5173be 100644 (file)
@@ -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)
index d849c1651b61063111d747f4f241d73fc43ed316..77d7b9acac7881c085de6f95d32dea3b692d02ea 100644 (file)
@@ -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
index a439cbb1898e3daa0533d51819ed2d2efa3a2e78..21ae166108dd81fa62b6647da6b5a85406bbf0a4 100644 (file)
@@ -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;
index 37af57a29656e01ca8d95f0568c72a802a097f91..88cc143809fb18b242fb3bd1f2966fef457bf3f6 100644 (file)
  *
  */
 
+/* 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 (file)
index 0000000..80170bd
--- /dev/null
@@ -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.
+