Hi, -File arch/i86/mm/user.c is now only C. The assembly functions were moved to arch/i86/mm/segment.c -Changes in several Makefile's and Makefile-rules to support compiling using ia16-unknown-elks-gcc -Addition of a C runtime library function needed by ia16-unknown-elks-gcc The kernel was compiled with BCC and tested with QEMU. Code size was reduced in 16 bytes. Compilation using BCC is as usual. To actually compile using ia16-unknown-elks-gcc you need: 1. The ia16-unknown-elks toolchain and a helper named att2as86. In later posts I'll explain how to build them. 2. To have the binaries of the above utilities in your PATH 3. Rename the following files from *.c to *.S arch/i86/kernel/bios16.c arch/i86/kernel/irqtab.c arch/i86/kernel/printreg.c arch/i86/mm/segment.c 4. Apply the following patch: ***************************************************************************** diff -Nur elks.orig/arch/i86/kernel/Makefile elks/arch/i86/kernel/Makefile --- elks.orig/arch/i86/kernel/Makefile 2015-06-12 10:31:05.309516062 -0500 +++ elks/arch/i86/kernel/Makefile 2015-06-12 10:59:04.241934884 -0500 @@ -47,6 +47,12 @@ ######################################################################### # Commands. +irqtab.o: irqtab.s + +bios16.o: bios16.s + +printreg.o: printreg.s + entry.o: entry.s as86 -0 -u -o entry.o entry.s diff -Nur elks.orig/arch/i86/mm/Makefile elks/arch/i86/mm/Makefile --- elks.orig/arch/i86/mm/Makefile 2015-06-12 10:31:05.553638057 -0500 +++ elks/arch/i86/mm/Makefile 2015-06-12 10:59:04.413934880 -0500 @@ -40,6 +40,8 @@ ######################################################################### # Commands. +segment.o: segment.s + all: mm.a mm.a: $(OBJS) ***************************************************************************** 5. In file Makefile-rules, uncomment the line: #USEIA16 = y Steps 3 and 4 also work to compile with BCC, but the renaming of the files cannot be done with patches. Once steps 3 and 4 are done, only step 5 is the difference to use one or another compiler. Using ia16-unknown-elks-gcc with flag -Os resulted in savings in code size of 3056 bytes, compared to BCC. The produced kernel boots but fails to recognize the disk. Probably this is because the compilers have different calling conventions. Juan
diff -Nur elks.orig/arch/i86/lib/divmodsi3.s elks/arch/i86/lib/divmodsi3.s --- elks.orig/arch/i86/lib/divmodsi3.s 1969-12-31 18:00:00.000000000 -0600 +++ elks/arch/i86/lib/divmodsi3.s 2015-06-11 15:21:41.000000000 -0500 @@ -0,0 +1,90 @@ + + .text + .extern ldivmod + .extern ludivmod + + .globl ___divsi3 + .even + +___divsi3: + push bp + mov bp,sp + push bx + push cx + push di + mov ax,4[bp] + mov bx,6[bp] + mov cx,8[bp] + mov di,10[bp] + call ldivmod + mov dx,di + mov ax,cx + pop di + pop cx + pop bx + pop bp + ret + + .globl ___modsi3 + .even + +___modsi3: + push bp + mov bp,sp + push bx + push cx + push di + mov ax,4[bp] + mov bx,6[bp] + mov cx,8[bp] + mov di,10[bp] + call ldivmod + mov dx,bx + pop di + pop cx + pop bx + pop bp + ret + + .globl ___udivsi3 + .even + +___udivsi3: + push bp + mov bp,sp + push bx + push cx + push di + mov ax,4[bp] + mov bx,6[bp] + mov cx,8[bp] + mov di,10[bp] + call ludivmod + mov dx,di + mov ax,cx + pop di + pop cx + pop bx + pop bp + ret + + .globl ___umodsi3 + .even + +___umodsi3: + push bp + mov bp,sp + push bx + push cx + push di + mov ax,4[bp] + mov bx,6[bp] + mov cx,8[bp] + mov di,10[bp] + call ludivmod + mov dx,bx + pop di + pop cx + pop bx + pop bp + ret diff -Nur elks.orig/arch/i86/lib/Makefile elks/arch/i86/lib/Makefile --- elks.orig/arch/i86/lib/Makefile 2015-04-26 11:39:15.000000000 -0500 +++ elks/arch/i86/lib/Makefile 2015-06-11 15:13:23.000000000 -0500 @@ -29,7 +29,13 @@ ######################################################################### # Objects to be compiled. +ifeq ($(USEIA16), y) +OBJS =peekb.o peekw.o pokew.o bitops.o \ + memmove.o string.o fmemset.o border.o setupw.o \ + ldivmod.o divmodsi3.o +else OBJS = $(IOBJS) $(JOBJS) $(LLOBJS) $(LXOBJS) +endif # compiler support for integer arithmetic @@ -39,14 +45,14 @@ JOBJS =inport.o inportb.o outport.o outportb.o \ peekb.o peekw.o pokew.o bitops.o \ - memmove.o string.o fmemset.o border.o + memmove.o string.o fmemset.o border.o setupw.o # ntohl.o ntohs.o # compiler support for long arithmetic on little-endian (normal) longs LLOBJS =laddl.o landl.o lcmpl.o lcoml.o ldecl.o ldivl.o ldivul.o \ leorl.o lincl.o lmodl.o lmodul.o lmull.o lnegl.o lorl.o \ - lsll.o lsrl.o lsrul.o lsubl.o ltstl.o setupw.o + lsll.o lsrl.o lsrul.o lsubl.o ltstl.o # compiler support for long arithmetic on all longs diff -Nur elks.orig/arch/i86/Makefile elks/arch/i86/Makefile --- elks.orig/arch/i86/Makefile 2015-04-26 11:39:15.000000000 -0500 +++ elks/arch/i86/Makefile 2015-06-09 15:25:22.000000000 -0500 @@ -85,10 +85,23 @@ toolkit: ${MAKE} -C tools all +ifeq ($(USEIA16), y) $(BASEDIR)/include/arch/asm-offsets.h: kernel/asm-offsets.c + echo '#ifndef ASM_OFFSETS_H' > $(BASEDIR)/include/arch/asm-offsets.h + echo '#define ASM_OFFSETS_H' >> $(BASEDIR)/include/arch/asm-offsets.h $(CC) $(CFLAGS) -S -o asm-offsets.s kernel/asm-offsets.c + sed -e '/^\tm/ !d' \ + -e "s/\(.*\t\\$$\)/\#define /" \ + -e "s/\([0-9][0-9]*\),\t_\([a-zA-Z][_0-9a-zA-Z]*\)/\2 \1/" \ + < asm-offsets.s >> $(BASEDIR)/include/arch/asm-offsets.h + echo '#endif' >> $(BASEDIR)/include/arch/asm-offsets.h + rm asm-offsets.s + +else +$(BASEDIR)/include/arch/asm-offsets.h: kernel/asm-offsets.c echo '#ifndef ASM_OFFSETS_H' > $(BASEDIR)/include/arch/asm-offsets.h echo '#define ASM_OFFSETS_H' >> $(BASEDIR)/include/arch/asm-offsets.h + $(CC) $(CFLAGS) -S -o asm-offsets.s kernel/asm-offsets.c sed -e '/^[^m].*/ d' \ -e 's/\],/ /' \ -e 's/ #/ /' \ @@ -100,6 +113,8 @@ echo '#endif' >> $(BASEDIR)/include/arch/asm-offsets.h rm asm-offsets.s +endif + ######################################################################### # Image selection. diff -Nur elks.orig/arch/i86/mm/Makefile elks/arch/i86/mm/Makefile --- elks.orig/arch/i86/mm/Makefile 2015-06-11 13:27:31.000000000 -0500 +++ elks/arch/i86/mm/Makefile 2015-06-10 18:49:05.000000000 -0500 @@ -35,7 +35,7 @@ ######################################################################### # Objects to be compiled. -OBJS = init.o malloc.o user.o +OBJS = init.o malloc.o user.o segment.o ######################################################################### # Commands. diff -Nur elks.orig/arch/i86/mm/segment.c elks/arch/i86/mm/segment.c --- elks.orig/arch/i86/mm/segment.c 2015-06-11 13:27:16.000000000 -0500 +++ elks/arch/i86/mm/segment.c 2015-06-10 17:24:19.000000000 -0500 @@ -0,0 +1,123 @@ +/* + * Assembly user access routines for the kernel. + */ + +#include <arch/asm-offsets.h> + +#ifndef S_SPLINT_S +#asm + + .text + +/* void memcpy_fromfs(void *daddr, void *saddr, size_t len);*/ + .globl _memcpy_fromfs + +_memcpy_fromfs: + + push bp + mov bp,sp + mov bx,_current + mov dx,es + mov ax,ds + mov es,ax + mov ds,TASK_USER_DS[bx] + mov ax,di + mov di,4[bp] + mov bx,si + mov si,6[bp] + mov cx,8[bp] + cld + rep + movsb + mov si,bx + mov di,ax + mov ax,es + mov ds,ax + mov es,dx + pop bp + ret + +/* void memcpy_tofs(void *daddr, void *saddr, size_t len);*/ + .globl _memcpy_tofs + +_memcpy_tofs: + + push bp + mov bp,sp + mov bx,_current + mov dx,es + mov es,TASK_USER_DS[bx] + mov ax,di + mov di,4[bp] + mov bx,si + mov si,6[bp] + mov cx,8[bp] + cld + rep + movsb + mov si,bx + mov di,ax + mov es,dx + pop bp + ret + +/* void fmemcpy(dseg, dest, sseg, src, size); */ + .globl _fmemcpy + +_fmemcpy: + + push bp + mov bp,sp + push ds + mov dx,es + mov es,4[bp] + mov ax,di + lds di,6[bp] + mov bx,si + mov si,10[bp] + mov cx,12[bp] + cld + rep + movsb + mov si,bx + mov di,ax + mov es,dx + pop ds + pop bp + ret + +/* int strlen_fromfs(void *saddr); */ + + /* scasb uses es:di, not ds:si, so it is not necessary + * to save and restore ds + */ + .globl _strlen_fromfs + +_strlen_fromfs: + + push bp + mov bp,sp + mov bx,_current + mov dx,es + mov es,TASK_USER_DS[bx] ! source segment + mov bx,di + mov di,4[bp] ! source address + xor al,al ! search for NULL byte + cld + mov cx,#-1 + repne + scasb + sub di,4[bp] ! calc len +1 + dec di + mov ax,di ! save in local var ds + mov di,bx + mov es,dx + pop bp + ret + + .data + .extern _current + +#endasm +#endif + diff -Nur elks.orig/arch/i86/mm/user.c elks/arch/i86/mm/user.c --- elks.orig/arch/i86/mm/user.c 2015-06-11 13:27:16.000000000 -0500 +++ elks/arch/i86/mm/user.c 2015-06-09 17:22:19.000000000 -0500 @@ -4,9 +4,9 @@ #include <linuxmt/types.h> #include <linuxmt/sched.h> -#include <arch/segment.h> #include <linuxmt/mm.h> #include <linuxmt/errno.h> +#include <arch/segment.h> int verfy_area(void *p, size_t len) { @@ -27,33 +27,6 @@ return 0; } -void memcpy_fromfs(void *daddr, void *saddr, size_t len) -{ - /*@unused@*/ unsigned short int ds = current->t_regs.ds; - -#ifndef S_SPLINT_S -#asm - push si - push di - mov dx,es - mov bx,ds - mov es,bx - mov di,[bp+.memcpy_fromfs.daddr] ! destination address - mov ds,[bp+.memcpy_fromfs.ds] ! source segment (local variable) - mov si,[bp+.memcpy_fromfs.saddr] ! source address - mov cx,[bp+.memcpy_fromfs.len] ! number of bytes to copy - cld - rep - movsb - mov ds,bx - mov es,dx - pop di - pop si -#endasm -#endif - -} - int verified_memcpy_fromfs(void *daddr, void *saddr, size_t len) { int err = verify_area(VERIFY_READ, saddr, len); @@ -66,29 +39,6 @@ return 0; } -void memcpy_tofs(void *daddr, void *saddr, size_t len) -{ - /*@unused@*/ unsigned short int es = current->t_regs.ds; - -#ifndef S_SPLINT_S -#asm - push si - push di - mov dx,es - mov es,[bp+.memcpy_tofs.es] ! destination segment (local variable) - mov di,[bp+.memcpy_tofs.daddr] ! destination address - mov si,[bp+.memcpy_tofs.saddr] ! source address - mov cx,[bp+.memcpy_tofs.len] ! number of bytes to copy - cld - rep - movsb - mov es,dx - pop di - pop si -#endasm -#endif -} - int verified_memcpy_tofs(void *daddr, void *saddr, size_t len) { int err = verify_area(VERIFY_WRITE, daddr, len); @@ -101,38 +51,6 @@ return 0; } -/* fmemcpy(dseg, dest, sseg, src, size); */ - -#ifndef S_SPLINT_S -#asm - - .globl _fmemcpy - -_fmemcpy: - push bp - mov bp, sp - push di - push si - push ds - push es - pushf - mov es, 4[bp] - lds di, 6[bp] - mov si, 10[bp] - mov cx, 12[bp] - cld ! Must move upwards... - rep - movsb - popf - pop es - pop ds - pop si - pop di - pop bp - ret -#endasm -#endif - #if 0 int fstrlen(unsigned short int dseg, unsigned short int doff) @@ -147,40 +65,6 @@ #endif -#if 1 - -int strlen_fromfs(void *saddr) -{ - int ds = (int) current->t_regs.ds; - - /* scasb uses es:di, not ds:si, so it is not necessary - * to save and restore ds - */ - -#ifndef S_SPLINT_S -#asm - - push di - mov dx,es - mov es,[bp+.strlen_fromfs.ds] ! source segment (local variable) - mov di,[bp+.strlen_fromfs.saddr] ! source address - cld - xor al,al ! search for NULL byte - mov cx,#-1 - repne - scasb - sub di,[bp+.strlen_fromfs.saddr] ! calc len +1 - dec di - mov [bp+.strlen_fromfs.ds],di ! save in local var ds - mov es,dx - pop di -#endasm -#endif - - return ds; -} -#endif - unsigned long int get_user_long(void *dv) { unsigned long retv; diff -Nur elks.orig/Makefile-rules elks/Makefile-rules --- elks.orig/Makefile-rules 2015-04-26 11:39:15.000000000 -0500 +++ elks/Makefile-rules 2015-06-10 18:25:27.000000000 -0500 @@ -57,6 +57,8 @@ ARCH = i86 +#USEIA16 = y + ######################################################################### # ROOT_DEV specifies the default root-device when making the image. # This does not yet work under ELKS. See include/linuxmt/config.h to @@ -177,33 +179,63 @@ # Define CPU-specific flags. ifeq ($(MK_CPU), 8086) +ifeq ($(USEIA16), y) + CPU_AS = -0 + CPU_CC = -mtune=i8086 -fno-inline -fdata-sections -ffunction-sections -mseparate-code-segment -Wl,--gc-sections + CPU_LD = -0 +else CPU_AS = -0 CPU_CC = -0 CPU_LD = -0 endif +endif ifeq ($(MK_CPU), 80186) +ifeq ($(USEIA16), y) + CPU_AS = -1 + CPU_CC = -mtune=i80186 -fno-inline -fdata-sections -ffunction-sections -mseparate-code-segment -Wl,--gc-sections + CPU_LD = -0 +else CPU_AS = -1 CPU_CC = -0 CPU_LD = -0 endif +endif ifeq ($(MK_CPU), 80286) +ifeq ($(USEIA16), y) + CPU_AS = -2 + CPU_CC = -mtune=i80286 -fno-inline -fdata-sections -ffunction-sections -mseparate-code-segment -Wl,--gc-sections + CPU_LD = -0 +else CPU_AS = -2 CPU_CC = -0 CPU_LD = -0 endif +endif ifeq ($(MK_CPU), 80386) +ifeq ($(USEIA16), y) + CPU_AS = -3 + CPU_CC = -3 + CPU_LD = -3 +else CPU_AS = -3 CPU_CC = -3 CPU_LD = -3 endif +endif ifeq ($(MK_CPU), 80486) +ifeq ($(USEIA16), y) CPU_AS = -3 CPU_CC = -3 CPU_LD = -3 +else + CPU_AS = -3 + CPU_CC = -3 + CPU_LD = -3 +endif endif ######################################################################### @@ -219,8 +251,8 @@ AR = ar CC_PROTO = gcc -I$(INCDIR) -M -MG $(CCDEFS) -CFLBASE = -O -I$(INCDIR) $(CCDEFS) -ansi -CPP = $(CC) -I$(INCDIR) -E $(CCDEFS) +CFLBASE = -I$(INCDIR) $(CCDEFS) +CPP = $(CC) -I$(INCDIR) -E $(CCDEFS) -ansi LINT = splint LINTLEVEL = -weak LCFLAGS = -I$(INCDIR) $(CCDEFS) @@ -230,16 +262,30 @@ ifneq ($(USEBCC), N) +ifeq ($(USEIA16), y) +################################ +# Definitions using ia16-unknown-elks-gcc compiler + +AS = as86 +ASFLAGS = $(CPU_AS) $(ARCH_AS) +CC = ia16-unknown-elks-gcc +CFLAGS = $(CPU_CC) $(ARCH_CC) -Os $(CFLBASE) -Wall +LD = ld86 +LDFLAGS = $(CPU_LD) -s + +else ################################ # Definitions using BCC compiler AS = as86 ASFLAGS = $(CPU_AS) $(ARCH_AS) CC = bcc -CFLAGS = $(CPU_CC) $(ARCH_CC) $(CFLBASE) +CFLAGS = $(CPU_CC) $(ARCH_CC) -O $(CFLBASE) -ansi LD = ld86 LDFLAGS = $(CPU_LD) -s +endif + else ################################ @@ -248,7 +294,7 @@ AS = as ASFLAGS = CC = gcc -CFLAGS = -i $(CFLBASE) +CFLAGS = -i -O $(CFLBASE) -ansi LD = ld LDFLAGS = -s -x @@ -266,9 +312,19 @@ .S.s: gcc -E -traditional -I$(INCDIR) $(CCDEFS) -o $*.s $< +ifeq ($(USEIA16), y) +.c.o: + $(CC) $(CFLAGS) -S -o $*.s $< + att2as86 < $*.s > $*.asm + $(AS) $(ASFLAGS) -u -o $*.o $*.asm + rm $*.s $*.asm + +else .c.o: $(CC) $(CFLAGS) -c -o $*.o $< +endif + ######################################################################### # Default target, to allow standard targets to be included. This simply # allows `make elks` to be called from any directory in the tree, and