Messages in this thread Patch in this message | | | From | Alan Modra <> | Subject | linux i386 asm changes | Date | Sun, 29 Mar 1998 23:47:54 +0930 (CST) |
| |
Hi Linus, There are many places in the kernel where 16 bit version of `mov reg,segreg' are used, that should really use the 32 bit version for speed and code size reasons. Here's a patch that changes as many as I could find. I'm using `movl %ax,%ds' rather than the more strictly correct `movl %eax,%ds' so that older versions of gas can still assemble the kernal. Also included in this patch, I make sure that segment reg pushes and pops use the explicit 32 bit version of the instruction.
Oh yes, compiled, but not yet booted this kernel :-) I can't afford to lose anything on my computer at the moment. Maybe someone with a spare machine could test this one?
diff -urp linux-2.1.91/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S --- linux-2.1.91/arch/i386/boot/compressed/head.S Sat Feb 21 17:14:36 1998 +++ linux/arch/i386/boot/compressed/head.S Sun Mar 29 15:02:15 1998 @@ -37,10 +37,10 @@ startup_32: cld cli movl $(__KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - mov %ax,%gs + movl %ax,%ds + movl %ax,%es + movl %ax,%fs + movl %ax,%gs #ifdef __SMP__ orw %bx,%bx # What state are we in BX=1 for SMP # 0 for boot diff -urp linux-2.1.91/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- linux-2.1.91/arch/i386/kernel/entry.S Thu Feb 12 11:25:27 1998 +++ linux/arch/i386/kernel/entry.S Sun Mar 29 23:00:37 1998 @@ -81,8 +81,8 @@ ENOSYS = 38 #define SAVE_ALL \ cld; \ - push %es; \ - push %ds; \ + pushl %es; \ + pushl %ds; \ pushl %eax; \ pushl %ebp; \ pushl %edi; \ @@ -91,8 +91,8 @@ ENOSYS = 38 pushl %ecx; \ pushl %ebx; \ movl $(__KERNEL_DS),%edx; \ - mov %dx,%ds; \ - mov %dx,%es; + movl %dx,%ds; \ + movl %dx,%es; #define RESTORE_ALL \ popl %ebx; \ @@ -102,8 +102,8 @@ ENOSYS = 38 popl %edi; \ popl %ebp; \ popl %eax; \ - pop %ds; \ - pop %es; \ + popl %ds; \ + popl %es; \ addl $4,%esp; \ iret @@ -231,7 +231,7 @@ ENTRY(divide_error) pushl $ SYMBOL_NAME(do_divide_error) ALIGN error_code: - push %ds + pushl %ds pushl %eax xorl %eax,%eax pushl %ebp @@ -241,17 +241,27 @@ error_code: decl %eax # eax = -1 pushl %ecx pushl %ebx +#if 1 xorl %ecx,%ecx # zero ecx cld mov %es,%cx # get the lower order bits of es +#else + cld +# Some older processors leave the top 16 bits of the 32 bit destination +# register undefined, rather than zeroed in the following instruction. +# This won't matter when restoring or loading a segment register from the +# stack. It may be a problem if any code reads the full 32 bit value. +# dosemu? kernel? Would somebody like to verify that this way is really OK? + movl %es,%cx +#endif xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) movl %esp,%edx xchgl %ecx, ES(%esp) # get the address and save es. pushl %eax # push the error code pushl %edx movl $(__KERNEL_DS),%edx - mov %dx,%ds - mov %dx,%es + movl %dx,%ds + movl %dx,%es GET_CURRENT(%ebx) call *%ecx addl $8,%esp diff -urp linux-2.1.91/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- linux-2.1.91/arch/i386/kernel/head.S Tue Mar 24 21:08:48 1998 +++ linux/arch/i386/kernel/head.S Sun Mar 29 15:02:15 1998 @@ -45,10 +45,10 @@ startup_32: */ cld movl $(__KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - mov %ax,%gs + movl %ax,%ds + movl %ax,%es + movl %ax,%fs + movl %ax,%gs #ifdef __SMP__ orw %bx,%bx jz 1f @@ -321,10 +321,10 @@ is386: pushl %ecx # restore original EF lidt idt_descr ljmp $(__KERNEL_CS),$1f 1: movl $(__KERNEL_DS),%eax # reload all the segment registers - mov %ax,%ds # after changing gdt. - mov %ax,%es - mov %ax,%fs - mov %ax,%gs + movl %ax,%ds # after changing gdt. + movl %ax,%es + movl %ax,%fs + movl %ax,%gs #ifdef __SMP__ movl $(__KERNEL_DS), %eax mov %ax,%ss # Reload the stack pointer (segment only) @@ -404,16 +404,16 @@ ignore_int: pushl %eax pushl %ecx pushl %edx - push %es - push %ds + pushl %es + pushl %ds movl $(__KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es + movl %ax,%ds + movl %ax,%es pushl $int_msg call SYMBOL_NAME(printk) popl %eax - pop %ds - pop %es + popl %ds + popl %es popl %edx popl %ecx popl %eax diff -urp linux-2.1.91/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h --- linux-2.1.91/arch/i386/kernel/irq.h Tue Mar 24 21:08:48 1998 +++ linux/arch/i386/kernel/irq.h Sun Mar 29 15:02:15 1998 @@ -83,8 +83,8 @@ static inline void irq_exit(int cpu, uns #define SAVE_ALL \ "cld\n\t" \ - "push %es\n\t" \ - "push %ds\n\t" \ + "pushl %es\n\t" \ + "pushl %ds\n\t" \ "pushl %eax\n\t" \ "pushl %ebp\n\t" \ "pushl %edi\n\t" \ @@ -93,8 +93,8 @@ static inline void irq_exit(int cpu, uns "pushl %ecx\n\t" \ "pushl %ebx\n\t" \ "movl $" STR(__KERNEL_DS) ",%edx\n\t" \ - "mov %dx,%ds\n\t" \ - "mov %dx,%es\n\t" + "movl %dx,%ds\n\t" \ + "movl %dx,%es\n\t" #define IRQ_NAME2(nr) nr##_interrupt(void) #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) diff -urp linux-2.1.91/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- linux-2.1.91/arch/i386/kernel/process.c Fri Mar 27 21:30:46 1998 +++ linux/arch/i386/kernel/process.c Sun Mar 29 23:32:08 1998 @@ -375,12 +375,12 @@ void machine_restart(char * __unused) registers don't have to be reloaded after switching to real mode: the values are consistent for real mode operation already. */ - __asm__ __volatile__ ("movw $0x0010,%%ax\n" - "\tmovw %%ax,%%ds\n" - "\tmovw %%ax,%%es\n" - "\tmovw %%ax,%%fs\n" - "\tmovw %%ax,%%gs\n" - "\tmovw %%ax,%%ss" : : : "eax"); + __asm__ __volatile__ ("movl $0x0010,%%eax\n" + "\tmovl %%ax,%%ds\n" + "\tmovl %%ax,%%es\n" + "\tmovl %%ax,%%fs\n" + "\tmovl %%ax,%%gs\n" + "\tmovl %%ax,%%ss" : : : "eax"); /* Jump to the 16-bit code that we copied earlier. It disables paging and the cache, switches to real mode, and jumps to the BIOS reset @@ -428,7 +428,7 @@ void exit_thread(void) if (last_task_used_math == current) last_task_used_math = NULL; /* forget local segments */ - __asm__ __volatile__("mov %w0,%%fs ; mov %w0,%%gs ; lldt %w0" + __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs ; lldt %w0" : /* no outputs */ : "r" (0)); current->tss.ldt = 0; @@ -583,8 +583,8 @@ void dump_thread(struct pt_regs * regs, dump->regs.eax = regs->eax; dump->regs.ds = regs->xds; dump->regs.es = regs->xes; - __asm__("mov %%fs,%0":"=r" (dump->regs.fs)); - __asm__("mov %%gs,%0":"=r" (dump->regs.gs)); + __asm__("movl %%fs,%0":"=r" (dump->regs.fs)); + __asm__("movl %%gs,%0":"=r" (dump->regs.gs)); dump->regs.orig_eax = regs->orig_eax; dump->regs.eip = regs->eip; dump->regs.cs = regs->xcs; diff -urp linux-2.1.91/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- linux-2.1.91/arch/i386/kernel/signal.c Thu Feb 12 11:25:27 1998 +++ linux/arch/i386/kernel/signal.c Sun Mar 29 16:19:31 1998 @@ -199,7 +199,7 @@ restore_sigcontext(struct pt_regs *regs, && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ goto badframe; \ - __asm__ __volatile__("mov %w0,%%" #seg : : "r"(tmp)); } + __asm__ __volatile__("movl %w0,%%" #seg : : "r"(tmp)); } GET_SEG(gs); GET_SEG(fs); @@ -337,9 +337,9 @@ setup_sigcontext(struct sigcontext *sc, unsigned int tmp; tmp = 0; - __asm__("mov %%gs,%w0" : "=r"(tmp): "0"(tmp)); + __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp)); __put_user(tmp, (unsigned int *)&sc->gs); - __asm__("mov %%fs,%w0" : "=r"(tmp): "0"(tmp)); + __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp)); __put_user(tmp, (unsigned int *)&sc->fs); __put_user(regs->xes, (unsigned int *)&sc->es); @@ -427,7 +427,7 @@ static void setup_frame(int sig, struct regs->eip = (unsigned long) ka->sa.sa_handler; { unsigned long seg = __USER_DS; - __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + __asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg)); set_fs(USER_DS); regs->xds = seg; regs->xes = seg; @@ -492,7 +492,7 @@ static void setup_rt_frame(int sig, stru regs->eip = (unsigned long) ka->sa.sa_handler; { unsigned long seg = __USER_DS; - __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + __asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg)); set_fs(USER_DS); regs->xds = seg; regs->xes = seg; diff -urp linux-2.1.91/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- linux-2.1.91/arch/i386/kernel/traps.c Sat Feb 21 17:14:36 1998 +++ linux/arch/i386/kernel/traps.c Sun Mar 29 15:02:15 1998 @@ -68,19 +68,19 @@ out: \ #define get_seg_byte(seg,addr) ({ \ register unsigned char __res; \ -__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ +__asm__("pushl %%fs;movl %%ax,%%fs;movb %%fs:%2,%%al;popl %%fs" \ :"=a" (__res):"0" (seg),"m" (*(addr))); \ __res;}) #define get_seg_long(seg,addr) ({ \ register unsigned long __res; \ -__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ +__asm__("pushl %%fs;movl %%ax,%%fs;movl %%fs:%2,%%eax;popl %%fs" \ :"=a" (__res):"0" (seg),"m" (*(addr))); \ __res;}) #define _fs() ({ \ register unsigned short __res; \ -__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__asm__("movl %%fs,%%ax":"=a" (__res):); \ __res;}) void page_exception(void); diff -urp linux-2.1.91/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- linux-2.1.91/arch/i386/kernel/vm86.c Fri Jan 16 10:11:52 1998 +++ linux/arch/i386/kernel/vm86.c Sun Mar 29 15:02:15 1998 @@ -255,7 +255,7 @@ static void do_sys_vm86(struct kernel_vm mark_screen_rdonly(tsk); unlock_kernel(); __asm__ __volatile__( - "xorl %%eax,%%eax; mov %%ax,%%fs; mov %%ax,%%gs\n\t" + "xorl %%eax,%%eax; movl %%ax,%%fs; movl %%ax,%%gs\n\t" "movl %0,%%esp\n\t" "jmp ret_from_sys_call" : /* no outputs */ diff -urp linux-2.1.91/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c --- linux-2.1.91/drivers/char/apm_bios.c Tue Mar 24 21:08:50 1998 +++ linux/drivers/char/apm_bios.c Sun Mar 29 15:02:16 1998 @@ -231,10 +231,10 @@ extern unsigned long get_cmos_time(void) "pushl %%fs\n\t" \ "pushl %%gs\n\t" \ "xorl %%edx, %%edx\n\t" \ - "mov %%dx, %%ds\n\t" \ - "mov %%dx, %%es\n\t" \ - "mov %%dx, %%fs\n\t" \ - "mov %%dx, %%gs\n\t" + "movl %%dx, %%ds\n\t" \ + "movl %%dx, %%es\n\t" \ + "movl %%dx, %%fs\n\t" \ + "movl %%dx, %%gs\n\t" # define APM_DO_RESTORE_SEGS \ "popl %%gs\n\t" \ "popl %%fs\n\t" \ diff -urp linux-2.1.91/include/asm/processor.h linux/include/asm/processor.h --- linux-2.1.91/include/asm/processor.h Tue Mar 24 21:09:04 1998 +++ linux/include/asm/processor.h Sun Mar 29 15:02:16 1998 @@ -179,7 +179,7 @@ struct thread_struct { #define start_thread(regs, new_eip, new_esp) do {\ unsigned long seg = __USER_DS; \ - __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg)); \ + __asm__("movl %w0,%%fs ; movl %w0,%%gs":"=r" (seg) :"0" (seg)); \ set_fs(USER_DS); \ regs->xds = seg; \ regs->xes = seg; \ diff -urp linux-2.1.91/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- linux-2.1.91/include/asm-i386/processor.h Tue Mar 24 21:09:04 1998 +++ linux/include/asm-i386/processor.h Sun Mar 29 15:02:16 1998 @@ -179,7 +179,7 @@ struct thread_struct { #define start_thread(regs, new_eip, new_esp) do {\ unsigned long seg = __USER_DS; \ - __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg)); \ + __asm__("movl %w0,%%fs ; movl %w0,%%gs":"=r" (seg) :"0" (seg)); \ set_fs(USER_DS); \ regs->xds = seg; \ regs->xes = seg; \ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |