/* Linker script for DOS executables with separate data and text segments.
   Partly derived from dos-exe-small.ld in newlib-ia16 and elks-separate.ld. */

OUTPUT_FORMAT(binary)

DOS_PSP = 0x60;
MEMOFS = DOS_PSP * 16 - SIZEOF(.msdos_mz_hdr);

/* these GROUPs play the same role as GROUPS (segments) in OMF */
PGROUP = (MEMOFS + LOADADDR(.ptext)) / 16;
LGROUP = (MEMOFS + LOADADDR(.ltext)) / 16;
DGROUP = (MEMOFS + LOADADDR(.data)) / 16;
_DosDataSeg = DGROUP;
TGROUP = (MEMOFS + LOADADDR(.text)) / 16;
IGROUP = (MEMOFS + LOADADDR(.itext)) / 16;
I_GROUP = (MEMOFS + LOADADDR(.idata)) / 16;

INITSIZE = SIZEOF(.itext) + SIZEOF(.idata) + SIZEOF(.ibss);

SECTIONS
  {
    /* Fabricate a .exe header here.  Although libbfd does have an
       "i386msdos" back-end which produces an "MZ" exe header, it cannot do
       certain things (yet). */
    .msdos_mz_hdr : {
		/* Signature.  */
		SHORT (0x5a4d)
		/* Bytes in last 512-byte page.  */
		SHORT (LOADADDR (.ibss) % 512)
		/* Total number of 512-byte pages.  */
		SHORT (ALIGN(LOADADDR (.ibss), 512) / 512)
		/* Relocation entries.  */
		SHORT ((__msdos_mz_rel_end - __msdos_mz_rel_start) / 4)
		/* Header size in paragraphs.  */
		SHORT (SIZEOF(.msdos_mz_hdr) / 16)
		/* Minimum extra paragraphs.  */
		SHORT (ALIGN(SIZEOF (.ibss) + SIZEOF(.istack), 16) / 16)
		/* Maximum extra paragraphs.  */
		SHORT (0xffff)
		/* Initial %ss.  */
		SHORT (LOADADDR (.istack) / 16 )
		/* Initial %sp. */
		SHORT (LOADADDR (.istack) % 16 + SIZEOF(.istack))
		/* Padding for Checksum (unused) and initial cs:ip (0:0) */
		. = 0x18;
		/* Relocation table offset.  */
		SHORT (. + 4)
		/* Overlay number  */
		SHORT (0)
		/* Relocations  */
		HIDDEN (__msdos_mz_rel_start = .);
		*(.msdos_mz_reloc .msdos_mz_reloc.*)
		HIDDEN (__msdos_mz_rel_end = .);
		/* Padding */
                . = ALIGN (16);
    }

    /* Target PSP section.  */
    .ptext 0 : AT (SIZEOF(.msdos_mz_hdr)) {
		*(PSP)
    }

    /* Target low data+text sections.  */
    .ltext 0 : AT (LOADADDR(.ptext) + SIZEOF(.ptext)) {
		*(_IRQTEXT)
		*(_LOWTEXT)
		*(_IO_TEXT)
		*(_IO_FIXED_DATA)
    }

    /* Target data sections.  */
    .data 0 : AT (ALIGN(LOADADDR(.ltext) + SIZEOF(.ltext), 16)) {
		*(_FIXED_DATA)
		*(_BSS)
		*(EXCLUDE_FILE (config.obj iasmsupt.obj *init*.obj iprf.obj main.obj) .bss)
		*(_DATA)
		*(EXCLUDE_FILE (config.obj iasmsupt.obj *init*.obj iprf.obj main.obj) .data)
		*(_DATAEND)
		*(CONST)
		*(CONST2)
		*(EXCLUDE_FILE (config.obj iasmsupt.obj *init*.obj iprf.obj main.obj) .rodata)
		*(EXCLUDE_FILE (config.obj iasmsupt.obj *init*.obj iprf.obj main.obj) .rodata.*)
		*(DYN_DATA)
		ASSERT(. <= 0xfff8,
		    "Error: too large for a small-model .exe file.");
	}

    /* Target text sections.  */
    .text 0 : AT (ALIGN(LOADADDR(.data) + SIZEOF(.data), 16)) {
		*(HMA_TEXT_START)
		*(HMA_TEXT)
		_call_intr = CALL_INTR;
		_res_DosExec = RES_DOSEXEC;
		_res_read = RES_READ;
		_strlen = STRLEN;
		_fstrlen = FSTRLEN;
		_strlen = STRLEN;
		_fstrcmp = FSTRCMP;
		_strchr = STRCHR;
		_fstrchr = FSTRCHR;
		_fmemchr = FMEMCHR;
		_strcpy = STRCPY;
		_fmemcpy = FMEMCPY;
		_fstrcpy = FSTRCPY;
		_memcpy = MEMCPY;
		_fmemset = FMEMSET;
		_memset = MEMSET;
		_memcmp = MEMCMP;
		_fmemcmp = FMEMCMP;
		_network_redirector_mx = NETWORK_REDIRECTOR_MX;
		_execrh = EXECRH;
		_share_check = SHARE_CHECK;
		_share_open_check = SHARE_OPEN_CHECK;
		_share_close_file = SHARE_CLOSE_FILE;
		_share_access_check = SHARE_ACCESS_CHECK;
		_share_lock_unlock = SHARE_LOCK_UNLOCK;
		_share_is_file_open = SHARE_IS_FILE_OPEN;
		_call_nls = CALL_NLS;
		_fl_reset = FL_RESET;
		_fl_diskchanged = FL_DISKCHANGED;
		_fl_format = FL_FORMAT;
		_fl_read = FL_READ;
		_fl_write = FL_WRITE;
		_fl_verify = FL_VERIFY;
		_fl_setdisktype = FL_SETDISKTYPE;
		_fl_setmediatype = FL_SETMEDIATYPE;
		_fl_readkey = FL_READKEY;
		_fl_lba_ReadWrite = FL_LBA_READWRITE;
		_floppy_change = FLOPPY_CHANGE;
		_ReadPCClock = READPCCLOCK;
		_WritePCClock = WRITEPCCLOCK;
		_WriteATClock = WRITEATCLOCK;
		*(EXCLUDE_FILE (config.obj iasmsupt.obj *init*.obj iprf.obj main.obj) .text)
		*(HMA_TEXT_END)
		ASSERT(. <= 0x10000,
		    "Error: too large for a small-model .exe file.");
	}

    /* Target init text sections. */
    .itext 0 : AT (LOADADDR(.text) + SIZEOF(.text)) {
		*(INIT_TEXT_START)
		*(INIT_TEXT)
                _init_execrh = INIT_EXECRH;
                _init_memset = INIT_MEMSET;
                _init_fmemset = INIT_FMEMSET;
                _init_memcmp = INIT_MEMCMP;
                _init_fmemcmp = INIT_FMEMCMP;
                _init_memcpy = INIT_MEMCPY;
                _init_fmemcpy = INIT_FMEMCPY;
                _init_strcpy = INIT_STRCPY;
                _init_fstrcpy = INIT_FSTRCPY;
                _init_strlen = INIT_STRLEN;
                _init_fstrlen = INIT_FSTRLEN;
                _init_strchr = INIT_STRCHR;
                _UMB_get_largest = UMB_GET_LARGEST;
		_init_call_intr = INIT_CALL_INTR;
		_read = READ;
		_init_DosOpen = INIT_DOSOPEN;
		_close = CLOSE;
		_dup2 = DUP2;
		_lseek = LSEEK;
		_allocmem = ALLOCMEM;
		_init_PSPSet = INIT_PSPSET;
		_init_DosExec = INIT_DOSEXEC;
		_init_setdrive = INIT_SETDRIVE;
		_init_switchar = INIT_SWITCHAR;
		_keycheck = KEYCHECK;
		_set_DTA = SET_DTA;
		_DetectXMSDriver = DETECTXMSDRIVER;
		_init_call_XMScall = INIT_CALL_XMSCALL;
		__EnableA20 = _ENABLEA20;
		__DisableA20 = _DISABLEA20;
		*(.text)
		*(INIT_TEXT_END)
		ASSERT(. <= 0x10000,
		    "Error: too large for a small-model .exe file.");
	}

    /* Target init data sections.  */
    .idata 0 : AT (LOADADDR(.itext) + SIZEOF(.itext)) {
		*(ID_B)
		*(.data)
		*(.rodata) *(.rodata.*)
		*(ID_E)
	}
    .ibss (NOLOAD) : AT (LOADADDR(.idata) + SIZEOF(.idata)) {
		*(IB_B)
		*(.bss)
		*(IB_E)
	}
    .istack 0 (NOLOAD) : AT (LOADADDR(.ibss) + SIZEOF(.ibss)) {
		*(_STACK)
		. = 0x1000;
	}
    /DISCARD/ : { *(.*) }
  }
