linux i386 asm changes

Alan Modra (alan@spri.levels.unisa.edu.au)
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