*/
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" };
#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.
*/
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)
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();
extern VOID relerp();
extern VOID erpdmp();
extern VOID prntval();
+extern int lastExtendedAddress;
/* lklibr.c */
extern VOID addfile();
/* lkihx.c */
extern VOID ihx();
-
+extern VOID ihxEntendedLinearAddress(addr_t);
/* lkstore.c */
extern char *StoreString( char *str );
/* SD added this to change
strcmpi --> strcmp (strcmpi NOT ANSI) */
#define strcmpi strcmp
+
* - 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;
/*
#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
#define S_ORG 24 /* .org */
#define S_MODUL 25 /* .module */
#define S_ASCIS 26 /* .ascis */
+#define S_FLAT24 27 /* .flat24 */
/*
*/
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"
extern VOID aerr();
extern VOID diag();
extern VOID err();
+extern VOID warnBanner(void);
extern char * geterr();
extern VOID qerr();
extern VOID rerr();
/* asout.c */
extern int hibyte();
extern int lobyte();
+extern int byte3(int);
extern VOID out();
extern VOID outab();
extern VOID outarea();
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 );
}
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
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) {
} 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);
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
}
}
+/*)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
}
}
+/*)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
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
*
}
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;
+}
}
}
+/*)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()
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:
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:
{ 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 */
*/
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)
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
sdp.s_area = NULL;
sdp.s_areax = NULL;
sdp.s_addr = 0;
+ lastExtendedAddress = -1;
break;
case 'M':
case 'U':
uflag = 1;
break;
-
+ case 'r':
+ case 'R':
+ rflag = 1;
+ break;
case 'x':
case 'X':
xflag = 0;
*
*/
+/* 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
*/
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
*/
} 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!
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
}
/*
/* 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)) {
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
--- /dev/null
+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.
+