Re: [ERROR-2.1.120] APM compilation fails

Stephen.Rothwell@canb.auug.org.au
Mon, 07 Sep 1998 00:11:27 +1000


Hi,

Inaky Perez Gonzalez <inaky@peloncho.fis.ucm.es> writes:
>
> APM compilation fails under 2.1.120 w/ quite old binutils [I
> know I am to blame here, but just FYI]. It complains in statements
> like this [compiled to assembler apm_bios.c]:
>
> #APP
> pushfl
> cli
> pushl %ds
> pushl %es
> > movw %ebx, %ds
> > movw %ebx, %es
> > movw %ebx, %fs
> > movw %ebx, %gs
> lcall %cs:apm_bios_entry
> movl $0, %edi
> jnc 1f
> movl $1, %edi
> 1: popl %es
> popl %ds
> popfl
>
> With errors [a lot more]:
>
> /tmp/apm.s:193: Error: operands given don't match any known 386 instruction
> /tmp/apm.s:194: Error: operands given don't match any known 386 instruction
> /tmp/apm.s:195: Error: operands given don't match any known 386 instruction
> /tmp/apm.s:196: Error: operands given don't match any known 386 instruction
>
> Kernel 2.1.120, Debian 1.3.1 gcc 2.7.2.1, binutils
> cygnus-2.7.1 (with BFD 2.7.0.9).

Try this:

diff -ru linux-2.1.120/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- linux-2.1.120/drivers/char/apm_bios.c Sun Sep 6 17:44:28 1998
+++ linux/drivers/char/apm_bios.c Mon Sep 7 00:08:42 1998
@@ -52,6 +52,9 @@
* 1.5: Fix segment register reloading (in case of bad segments saved
* across BIOS call).
* Stephen ROthwell
+ * 1.6: Alternate solution to register reloading inspired by
+ * Gabriel Paubert <paubert@iram.es>
+ * Stephen Rothwell
*
* APM 1.1 Reference:
*
@@ -211,11 +214,6 @@
#define APM_CHECK_TIMEOUT (HZ)

/*
- * Save a segment register away
- */
-#define savesegment(seg, where) __asm__ __volatile__("movw %%" #seg ", %0\n" : "=m" (where))
-
-/*
* Forward declarations
*/
static void suspend(void);
@@ -263,7 +261,7 @@

static struct timer_list apm_timer;

-static char driver_version[] = "1.5"; /* no spaces */
+static char driver_version[] = "1.6"; /* no spaces */

#ifdef APM_DEBUG
static char * apm_event_name[] = {
@@ -354,45 +352,55 @@
static inline int apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
{
- u16 old_fs;
- u16 old_gs;
int error;

-#ifdef APM_ZERO_SEGS
- savesegment(fs, old_fs);
- savesegment(gs, old_gs);
-#endif
__asm__ __volatile__(
"pushfl\n\t"
#ifdef APM_NOINTS
"cli\n\t"
#endif
#ifdef APM_ZERO_SEGS
- "pushl %%ds\n\t"
+ "pushl %%gs\n\t"
+ "pushl %%fs\n\t"
"pushl %%es\n\t"
- "movw %9, %%ds\n\t"
- "movw %9, %%es\n\t"
- "movw %9, %%fs\n\t"
- "movw %9, %%gs\n\t"
+ "pushl %%ds\n\t"
+ "xor %%dx, %%dx\n\t"
+ "movw %%dx, %%ds\n\t"
+ "movw %%dx, %%es\n\t"
+ "movw %%dx, %%fs\n\t"
+ "movw %%dx, %%gs\n\t"
#endif
"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
"movl $0, %%edi\n\t"
"jnc 1f\n\t"
"movl $1, %%edi\n"
- "1:\tpopl %%es\n\t"
+ "1:\t"
+#ifdef APM_ZERO_SEGS
"popl %%ds\n\t"
- "popfl\n\t"
+ "popl %%es\n"
+ "2:\t"
+ "popl %%fs\n"
+ "3:\t"
+ "popl %%gs\n\t"
+ ".section fixup, \"ax\"\n"
+ "4:\t"
+ "movl $0, (%%esp)\n\t"
+ "jmp 2b\n"
+ "5:\t"
+ "movl $0, (%%esp)\n\t"
+ "jmp 3b\n\t"
+ ".previous\n\t"
+ ".section __ex_table, \"a\"\n\t"
+ ".align 4\n\t"
+ ".long 2b, 4b\n\t"
+ ".long 3b, 5b\n\t"
+ ".previous\n\t"
+#endif
+ "popfl"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
"=S" (*esi), "=D" (error)
: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-#ifdef APM_ZERO_SEGS
- , "r" (0)
-#endif
: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory");
-#ifdef APM_ZERO_SEGS
- loadsegment(fs, old_fs);
- loadsegment(gs, old_gs);
-#endif
return error;
}

@@ -402,44 +410,54 @@

static inline int apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in, u32 *eax)
{
- u16 old_fs;
- u16 old_gs;
int error;

-#ifdef APM_ZERO_SEGS
- savesegment(fs, old_fs);
- savesegment(gs, old_gs);
-#endif
__asm__ __volatile__(
"pushfl\n\t"
#ifdef APM_NOINTS
"cli\n\t"
#endif
#ifdef APM_ZERO_SEGS
- "pushl %%ds\n\t"
+ "pushl %%gs\n\t"
+ "pushl %%fs\n\t"
"pushl %%es\n\t"
- "movw %5, %%ds\n\t"
- "movw %5, %%es\n\t"
- "movw %5, %%fs\n\t"
- "movw %5, %%gs\n\t"
+ "pushl %%ds\n\t"
+ "xor %%dx, %%dx\n\t"
+ "movw %%dx, %%ds\n\t"
+ "movw %%dx, %%es\n\t"
+ "movw %%dx, %%fs\n\t"
+ "movw %%dx, %%gs\n\t"
#endif
"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
"movl $0, %%edi\n\t"
"jnc 1f\n\t"
"movl $1, %%edi\n"
- "1:\tpopl %%es\n\t"
+ "1:\t"
+#ifdef APM_ZERO_SEGS
"popl %%ds\n\t"
+ "popl %%es\n"
+ "2:\t"
+ "popl %%fs\n"
+ "3:\t"
+ "popl %%gs\n\t"
+ ".section fixup, \"ax\"\n"
+ "4:\t"
+ "movl $0, (%%esp)\n\t"
+ "jmp 2b\n"
+ "5:\t"
+ "movl $0, (%%esp)\n\t"
+ "jmp 3b\n\t"
+ ".previous\n\t"
+ ".section __ex_table, \"a\"\n\t"
+ ".align 4\n\t"
+ ".long 2b, 4b\n\t"
+ ".long 3b, 5b\n\t"
+ ".previous\n\t"
+#endif
"popfl\n\t"
: "=a" (*eax), "=D" (error)
: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-#ifdef APM_ZERO_SEGS
- , "r" (0)
-#endif
: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory");
-#ifdef APM_ZERO_SEGS
- loadsegment(fs, old_fs);
- loadsegment(gs, old_gs);
-#endif
return error;
}

Cheers,
Stephen

--
Stephen Rothwell                    Stephen.Rothwell@canb.auug.org.au

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/faq.html