ia16-elf-gcc: provide GNU LD linker script and symbols to link kernel.

The resulting kernel and sys.com do not work yet (kernel prints 123 only).
Some functions in sys.com are placeholders.
This commit is contained in:
Bart Oldeman 2017-12-19 10:40:39 -05:00 committed by Kenneth J Davis
parent 7bf4b77233
commit 71a7d0d264
10 changed files with 312 additions and 7 deletions

View File

@ -143,6 +143,15 @@ unsigned short getSS(void);
#ifdef __FAR #ifdef __FAR
#define I86 #define I86
#define __int__(intno) asm volatile("int " ## #intno)
static inline void disable(void)
{
asm volatile("cli");
}
static inline void enable(void)
{
asm volatile("sti");
}
#define far __far #define far __far
#define CDECL #define CDECL
#define VA_CDECL #define VA_CDECL

View File

@ -160,7 +160,14 @@ extern struct dhdr FAR ASM clk_dev; /* Clock device driver */
extern struct dhdr FAR ASM con_dev; /* Console device driver */ extern struct dhdr FAR ASM con_dev; /* Console device driver */
extern struct dhdr FAR ASM prn_dev; /* Generic printer device driver */ extern struct dhdr FAR ASM prn_dev; /* Generic printer device driver */
extern struct dhdr FAR ASM aux_dev; /* Generic aux device driver */ extern struct dhdr FAR ASM aux_dev; /* Generic aux device driver */
#ifndef __GNUC__
extern struct dhdr FAR ASM blk_dev; /* Block device (Disk) driver */ extern struct dhdr FAR ASM blk_dev; /* Block device (Disk) driver */
#else
extern struct dhdr ASM blk_dev;
#define DosTextSeg 0x70
#define DOSTEXT(x) (*(typeof(x) FAR *)MK_FP(DosTextSeg, (size_t)&(x)))
#define blk_dev DOSTEXT(blk_dev)
#endif
extern COUNT *error_tos, /* error stack */ extern COUNT *error_tos, /* error stack */
disk_api_tos, /* API handler stack - disk fns */ disk_api_tos, /* API handler stack - disk fns */
char_api_tos; /* API handler stack - char fns */ char_api_tos; /* API handler stack - char fns */

View File

@ -78,7 +78,7 @@ UWORD HMAFree BSS_INIT(0); /* first byte in HMA not yet used */
STATIC void InstallVDISK(void); STATIC void InstallVDISK(void);
#ifdef DEBUG #ifdef DEBUG
#ifdef __TURBOC__ #if defined(__TURBOC__) || defined(__GNUC__)
#define int3() __int__(3); #define int3() __int__(3);
#else #else
void int3() void int3()

View File

@ -887,6 +887,26 @@ __U4D:
LDIVMODU LDIVMODU
%endif %endif
%ifdef gcc
global ___udivsi3
___udivsi3: call ldivmodu
ret 8
global ___umodsi3
___umodsi3: call ldivmodu
mov dx, cx
mov ax, bx
ret 8
ldivmodu: LDIVMODU
global ___ashlsi3
___ashlsi3: LSHLU
global ___lshrsi3
___lshrsi3: LSHRU
%endif
times 0xd0 - ($-begin_hma) db 0 times 0xd0 - ($-begin_hma) db 0
; reserve space for far jump to cp/m routine ; reserve space for far jump to cp/m routine
times 5 db 0 times 5 db 0

186
kernel/kernel.ld Executable file
View File

@ -0,0 +1,186 @@
/* 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(.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). */
.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 (0)
/* Header size in paragraphs. */
SHORT (SIZEOF(.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 + padding */
. = ALIGN (32);
}
/* Target PSP section. */
.ptext 0 : AT (SIZEOF(.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)
_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;
_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_strlen = INIT_STRLEN;
_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/ : { *(.*) }
}

View File

@ -110,3 +110,29 @@
ret ret
%endmacro %endmacro
%macro LSHLU 0
pop bx
pop ax
pop dx
pop cx
push bx
jcxz %%ret
%%loop: shl ax, 1
rcl dx, 1
loop %%loop
%%ret: ret 6
%endmacro
%macro LSHRU 0
pop bx
pop ax
pop dx
pop cx
push bx
jcxz %%ret
%%loop: shr dx, 1
rcr ax, 1
loop %%loop
%%ret: ret 6
%endmacro

View File

@ -158,7 +158,7 @@ initclk.obj: initclk.c $(INITHEADERS) $(TARGET).lnk
#the string functions for INIT_TEXT #the string functions for INIT_TEXT
iasmsupt.obj: asmsupt.asm $(TARGET).lnk iasmsupt.obj: asmsupt.asm $(TARGET).lnk
$(NASM) -D$(COMPILER) -D_INIT $(NASMFLAGS) -f obj -o iasmsupt.obj asmsupt.asm $(NASM) -D$(COMPILER) -D_INIT -f obj $(NASMFLAGS) -o iasmsupt.obj asmsupt.asm
#the printf for INIT_TEXT - yet another special case, this file includes prf.c #the printf for INIT_TEXT - yet another special case, this file includes prf.c
iprf.obj: iprf.c prf.c $(HDR)portab.h $(TARGET).lnk iprf.obj: iprf.c prf.c $(HDR)portab.h $(TARGET).lnk

View File

@ -3,7 +3,7 @@
# #
CC=ia16-elf-gcc -c CC=ia16-elf-gcc -c
CL=echo ia16-elf-gcc CL=ia16-elf-gcc
INCLUDEPATH=. INCLUDEPATH=.
!if $(XCPU) != 186 !if $(XCPU) != 186
@ -26,6 +26,7 @@ TARGET=KGC
# heavy stuff - building # heavy stuff - building
# #
# -mcmodel=small small memory model (small code/small data) # -mcmodel=small small memory model (small code/small data)
# -Os -> favor code size over execution time in optimizations
# -fleading-underscore underscores leading field for DOS compiler compat # -fleading-underscore underscores leading field for DOS compiler compat
# -fno-common no "common" variables, just BSS for uninitialized data # -fno-common no "common" variables, just BSS for uninitialized data
# -fpack-struct pack structure members # -fpack-struct pack structure members
@ -35,17 +36,17 @@ TARGET=KGC
# -w disable warnings for now # -w disable warnings for now
# -Werror treat all warnings as errors # -Werror treat all warnings as errors
ALLCFLAGS=-I../hdr $(TARGETOPT) $(ALLCFLAGS) -mcmodel=small -fleading-underscore -fno-common -fpack-struct -ffreestanding -fcall-used-es -mrtd -w -Werror ALLCFLAGS=-I../hdr $(TARGETOPT) $(ALLCFLAGS) -mcmodel=small -fleading-underscore -fno-common -fpack-struct -ffreestanding -fcall-used-es -mrtd -w -Werror -Os
INITCFLAGS=$(ALLCFLAGS) -o $@ INITCFLAGS=$(ALLCFLAGS) -o $@
CFLAGS=$(ALLCFLAGS) -o $@ CFLAGS=$(ALLCFLAGS) -o $@
NASMFLAGS=$(NASMFLAGS) -f elf -o $@ NASMFLAGS=$(NASMFLAGS) -f elf -o $@
DIRSEP=/ DIRSEP=/
RM=rm -f RM=rm -f
CP=echo cp CP=cp
ECHOTO=echo>> ECHOTO=echo>>
INITPATCH=@echo > /dev/null INITPATCH=@echo > /dev/null
CLDEF=1 CLDEF=1
CLT=gcc -DDOSC_TIME_H -I../hdr -o $@ CLT=gcc -DDOSC_TIME_H -I../hdr -o $@
CLC=$(CLT) CLC=$(CLT)
XLINK=echo $(XLINK) debug all op symfile format dos option map,statics,verbose F { $(OBJS) } L ../lib/device.lib N kernel.exe $# XLINK=$(CL) -Tkernel.ld -Wl,-Map,kernel.map -o kernel.exe $(OBJS) -Wl,--whole-archive ../drivers/device.lib -Wl,--no-whole-archive $#

View File

@ -117,6 +117,52 @@ struct SREGS {
struct _diskfree_t { struct _diskfree_t {
unsigned short avail_clusters, sectors_per_cluster, bytes_per_sector; unsigned short avail_clusters, sectors_per_cluster, bytes_per_sector;
}; };
int int86(int ivec, union REGS *in, union REGS *out)
{
}
int intdos(union REGS *in, union REGS *out)
{
}
int intdosx(union REGS *in, union REGS *out, struct SREGS *s)
{
}
unsigned _dos_allocmem(unsigned size, unsigned *seg)
{
}
unsigned _dos_freemem(unsigned seg)
{
}
unsigned int _dos_getdiskfree(unsigned int drive,
struct diskfree_t *diskspace)
{
}
long filelength(int fhandle)
{
}
struct find_t {
char reserved[21];
unsigned char attrib;
unsigned short wr_time;
unsigned short wr_date;
unsigned long size;
char filename[13];
};
#define _A_NORMAL 0x00
#define _A_HIDDEN 0x02
#define _A_SYSTEM 0x04
int _dos_findfirst(const char *file_name, unsigned int attr,
struct find_t *find_tbuf)
{
}
#else #else
#include <io.h> #include <io.h>
#endif #endif
@ -194,7 +240,9 @@ int write(int fd, const void *buf, unsigned count)
} }
#define close _dos_close #define close _dos_close
#endif
#if defined(__WATCOMC__) || defined(__GNUC__)
int stat(const char *file_name, struct stat *statbuf) int stat(const char *file_name, struct stat *statbuf)
{ {
struct find_t find_tbuf; struct find_t find_tbuf;
@ -204,7 +252,9 @@ int stat(const char *file_name, struct stat *statbuf)
/* statbuf->st_attr = (ULONG)find_tbuf.attrib; */ /* statbuf->st_attr = (ULONG)find_tbuf.attrib; */
return ret; return ret;
} }
#endif
#ifdef __WATCOMC__
/* WATCOM's getenv is case-insensitive which wastes a lot of space /* WATCOM's getenv is case-insensitive which wastes a lot of space
for our purposes. So here's a simple case-sensitive one */ for our purposes. So here's a simple case-sensitive one */
char *getenv(const char *name) char *getenv(const char *name)

View File

@ -33,6 +33,12 @@ extern unsigned __brklvl;
#ifdef __GNUC__ #ifdef __GNUC__
#include <unistd.h> #include <unistd.h>
static inline int brk(void *addr)
{
char *brklvl = sbrk(0);
int *res = sbrk((char *)addr - brklvl);
return (res == (void *)-1) ? -1 : 0;
}
#endif #endif
#define BUSY (sizeof(size_t)-1) /* Bit set if memory block in use*/ #define BUSY (sizeof(size_t)-1) /* Bit set if memory block in use*/