Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision c15b37446cc540323e335d60ebc0166256615461)
+++ kernel/arch/ia32/include/asm.h	(revision 44c69b668c00d396162d5dd7c6d15d727c9b4a28)
@@ -429,4 +429,6 @@
 extern void asm_delay_loop(uint32_t);
 extern void asm_fake_loop(uint32_t);
+
+extern uintptr_t int_syscall;
 
 extern uintptr_t int_0;
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision c15b37446cc540323e335d60ebc0166256615461)
+++ kernel/arch/ia32/src/asm.S	(revision 44c69b668c00d396162d5dd7c6d15d727c9b4a28)
@@ -266,4 +266,90 @@
 	sysexit   /* return to userspace */
 
+/*
+ * This is the legacy syscall handler using the interrupt mechanism.
+ */
+.global int_syscall
+int_syscall:
+	subl $(ISTATE_SOFT_SIZE + 4), %esp
+
+	/*
+	 * Push syscall arguments onto the stack
+	 *
+	 * NOTE: The idea behind the order of arguments passed
+	 *       in registers is to use all scratch registers
+	 *       first and preserved registers next. An optimized
+	 *       libc syscall wrapper can make use of this setup.
+	 *       The istate structure is arranged in the way to support
+	 *       this idea.
+	 *
+	 */
+	movl %eax, ISTATE_OFFSET_EAX(%esp)
+	movl %ebx, ISTATE_OFFSET_EBX(%esp)
+	movl %ecx, ISTATE_OFFSET_ECX(%esp)
+	movl %edx, ISTATE_OFFSET_EDX(%esp)
+	movl %edi, ISTATE_OFFSET_EDI(%esp)
+	movl %esi, ISTATE_OFFSET_ESI(%esp)
+	movl %ebp, ISTATE_OFFSET_EBP(%esp)
+
+	/*
+	 * Save the selector registers.
+	 */
+	movl %gs, %ecx
+	movl %fs, %edx
+
+	movl %ecx, ISTATE_OFFSET_GS(%esp)
+	movl %edx, ISTATE_OFFSET_FS(%esp)
+
+	movl %es, %ecx
+	movl %ds, %edx
+		
+	movl %ecx, ISTATE_OFFSET_ES(%esp)
+	movl %edx, ISTATE_OFFSET_DS(%esp)
+
+	/*
+	 * Switch to kernel selectors.
+	 */
+	movl $16, %eax
+	movl %eax, %ds
+	movl %eax, %es
+		
+	movl $0, ISTATE_OFFSET_EBP_FRAME(%esp)
+	movl ISTATE_OFFSET_EIP(%esp), %eax
+	movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
+	leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
+		
+	cld
+	sti
+		
+	/* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
+	call syscall_handler
+			
+	CLEAR_NT_FLAG
+
+	/*
+	 * Restore the selector registers.
+	 */
+	movl ISTATE_OFFSET_GS(%esp), %ecx
+	movl ISTATE_OFFSET_FS(%esp), %edx
+
+	movl %ecx, %gs
+	movl %edx, %fs
+
+	movl ISTATE_OFFSET_ES(%esp), %ecx
+	movl ISTATE_OFFSET_DS(%esp), %edx
+			
+	movl %ecx, %es
+	movl %edx, %ds
+			
+	/*
+	 * Restore the preserved registers the handler cloberred itself
+	 * (i.e. EBP).
+	 */
+	movl ISTATE_OFFSET_EBP(%esp), %ebp
+			
+	addl $(ISTATE_SOFT_SIZE + 4), %esp
+	iret
+		
+
 /** Declare interrupt handlers
  *
@@ -272,54 +358,76 @@
  *
  */
-
 .macro handler i
 .global int_\i
 int_\i:
-	.ifeq \i - 0x30
-		/* Syscall handler */
-		subl $(ISTATE_SOFT_SIZE + 4), %esp
-
+	/*
+	 * This macro distinguishes between two versions of ia32
+	 * exceptions. One version has error word and the other
+	 * does not have it. The latter version fakes the error
+	 * word on the stack so that the handlers and istate_t
+	 * can be the same for both types.
+	 */
+	.iflt \i - 32
+		.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
+			/*
+			 * Exception with error word: do nothing
+			 */
+		.else
+			/*
+			 * Exception without error word: fake up one
+			 */
+			pushl $0
+		.endif
+	.else
 		/*
-		 * Push syscall arguments onto the stack
-		 *
-		 * NOTE: The idea behind the order of arguments passed
-		 *       in registers is to use all scratch registers
-		 *       first and preserved registers next. An optimized
-		 *       libc syscall wrapper can make use of this setup.
-		 *       The istate structure is arranged in the way to support
-		 *       this idea.
-		 *
+		 * Interrupt: fake up one
 		 */
-		movl %eax, ISTATE_OFFSET_EAX(%esp)
-		movl %ebx, ISTATE_OFFSET_EBX(%esp)
-		movl %ecx, ISTATE_OFFSET_ECX(%esp)
-		movl %edx, ISTATE_OFFSET_EDX(%esp)
-		movl %edi, ISTATE_OFFSET_EDI(%esp)
-		movl %esi, ISTATE_OFFSET_ESI(%esp)
-		movl %ebp, ISTATE_OFFSET_EBP(%esp)
-
-		/*
-		 * Save the selector registers.
-		 */
-		movl %gs, %ecx
-		movl %fs, %edx
-
-		movl %ecx, ISTATE_OFFSET_GS(%esp)
-		movl %edx, ISTATE_OFFSET_FS(%esp)
-
-		movl %es, %ecx
-		movl %ds, %edx
-		
-		movl %ecx, ISTATE_OFFSET_ES(%esp)
-		movl %edx, ISTATE_OFFSET_DS(%esp)
-
-		/*
-		 * Switch to kernel selectors.
-		 */
-		movl $16, %eax
-		movl %eax, %ds
-		movl %eax, %es
-		
-		movl $0, ISTATE_OFFSET_EBP_FRAME(%esp)
+		pushl $0
+	.endif
+	
+	subl $ISTATE_SOFT_SIZE, %esp
+	
+	/*
+	 * Save the general purpose registers.
+	 */
+	movl %eax, ISTATE_OFFSET_EAX(%esp)
+	movl %ebx, ISTATE_OFFSET_EBX(%esp)
+	movl %ecx, ISTATE_OFFSET_ECX(%esp)
+	movl %edx, ISTATE_OFFSET_EDX(%esp)
+	movl %edi, ISTATE_OFFSET_EDI(%esp)
+	movl %esi, ISTATE_OFFSET_ESI(%esp)
+	movl %ebp, ISTATE_OFFSET_EBP(%esp)
+	
+	/*
+	 * Save the selector registers.
+	 */
+	movl %gs, %eax
+	movl %fs, %ebx
+	movl %es, %ecx
+	movl %ds, %edx
+	
+	movl %eax, ISTATE_OFFSET_GS(%esp)
+	movl %ebx, ISTATE_OFFSET_FS(%esp)
+	movl %ecx, ISTATE_OFFSET_ES(%esp)
+	movl %edx, ISTATE_OFFSET_DS(%esp)
+	
+	/*
+	 * Switch to kernel selectors.
+	 */
+	movl $16, %eax
+	movl %eax, %ds
+	movl %eax, %es
+	
+	/*
+	 * Imitate a regular stack frame linkage.
+	 * Stop stack traces here if we came from userspace.
+	 */
+	cmpl $8, ISTATE_OFFSET_CS(%esp)
+	jz 0f
+	xorl %ebp, %ebp
+	
+	0:
+	
+		movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
 		movl ISTATE_OFFSET_EIP(%esp), %eax
 		movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
@@ -327,149 +435,41 @@
 		
 		cld
-		sti
-		
-		/* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
-		call syscall_handler
-			
+		
+		pushl %esp   /* pass istate address */
+		pushl $(\i)  /* pass intnum */
+		
+		/* Call exc_dispatch(intnum, istate) */
+		call exc_dispatch
+		
+		addl $8, %esp  /* clear arguments from the stack */
+		
 		CLEAR_NT_FLAG
-
+		
 		/*
 		 * Restore the selector registers.
 		 */
-		movl ISTATE_OFFSET_GS(%esp), %ecx
-		movl ISTATE_OFFSET_FS(%esp), %edx
-
-		movl %ecx, %gs
-		movl %edx, %fs
-
+		movl ISTATE_OFFSET_GS(%esp), %eax
+		movl ISTATE_OFFSET_FS(%esp), %ebx
 		movl ISTATE_OFFSET_ES(%esp), %ecx
 		movl ISTATE_OFFSET_DS(%esp), %edx
-			
+		
+		movl %eax, %gs
+		movl %ebx, %fs
 		movl %ecx, %es
 		movl %edx, %ds
-			
+		
 		/*
-		 * Restore the preserved registers the handler cloberred itself
-		 * (i.e. EBP).
+		 * Restore the scratch registers and the preserved
+		 * registers the handler cloberred itself
+		 * (i.e. EBX and EBP).
 		 */
+		movl ISTATE_OFFSET_EAX(%esp), %eax
+		movl ISTATE_OFFSET_EBX(%esp), %ebx
+		movl ISTATE_OFFSET_ECX(%esp), %ecx
+		movl ISTATE_OFFSET_EDX(%esp), %edx
 		movl ISTATE_OFFSET_EBP(%esp), %ebp
-			
+		
 		addl $(ISTATE_SOFT_SIZE + 4), %esp
 		iret
-		
-	.else
-		/*
-		 * This macro distinguishes between two versions of ia32
-		 * exceptions. One version has error word and the other
-		 * does not have it. The latter version fakes the error
-		 * word on the stack so that the handlers and istate_t
-		 * can be the same for both types.
-		 */
-		.iflt \i - 32
-			.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
-				/*
-				 * Exception with error word: do nothing
-				 */
-			.else
-				/*
-				 * Exception without error word: fake up one
-				 */
-				pushl $0
-			.endif
-		.else
-			/*
-			 * Interrupt: fake up one
-			 */
-			pushl $0
-		.endif
-		
-		subl $ISTATE_SOFT_SIZE, %esp
-		
-		/*
-		 * Save the general purpose registers.
-		 */
-		movl %eax, ISTATE_OFFSET_EAX(%esp)
-		movl %ebx, ISTATE_OFFSET_EBX(%esp)
-		movl %ecx, ISTATE_OFFSET_ECX(%esp)
-		movl %edx, ISTATE_OFFSET_EDX(%esp)
-		movl %edi, ISTATE_OFFSET_EDI(%esp)
-		movl %esi, ISTATE_OFFSET_ESI(%esp)
-		movl %ebp, ISTATE_OFFSET_EBP(%esp)
-		
-		/*
-		 * Save the selector registers.
-		 */
-		movl %gs, %eax
-		movl %fs, %ebx
-		movl %es, %ecx
-		movl %ds, %edx
-		
-		movl %eax, ISTATE_OFFSET_GS(%esp)
-		movl %ebx, ISTATE_OFFSET_FS(%esp)
-		movl %ecx, ISTATE_OFFSET_ES(%esp)
-		movl %edx, ISTATE_OFFSET_DS(%esp)
-		
-		/*
-		 * Switch to kernel selectors.
-		 */
-		movl $16, %eax
-		movl %eax, %ds
-		movl %eax, %es
-		
-		/*
-		 * Imitate a regular stack frame linkage.
-		 * Stop stack traces here if we came from userspace.
-		 */
-		cmpl $8, ISTATE_OFFSET_CS(%esp)
-		jz 0f
-		xorl %ebp, %ebp
-		
-		0:
-		
-			movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
-			movl ISTATE_OFFSET_EIP(%esp), %eax
-			movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
-			leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
-			
-			cld
-			
-			pushl %esp   /* pass istate address */
-			pushl $(\i)  /* pass intnum */
-			
-			/* Call exc_dispatch(intnum, istate) */
-			call exc_dispatch
-			
-			addl $8, %esp  /* clear arguments from the stack */
-			
-			CLEAR_NT_FLAG
-			
-			/*
-			 * Restore the selector registers.
-			 */
-			movl ISTATE_OFFSET_GS(%esp), %eax
-			movl ISTATE_OFFSET_FS(%esp), %ebx
-			movl ISTATE_OFFSET_ES(%esp), %ecx
-			movl ISTATE_OFFSET_DS(%esp), %edx
-			
-			movl %eax, %gs
-			movl %ebx, %fs
-			movl %ecx, %es
-			movl %edx, %ds
-			
-			/*
-			 * Restore the scratch registers and the preserved
-			 * registers the handler cloberred itself
-			 * (i.e. EBX and EBP).
-			 */
-			movl ISTATE_OFFSET_EAX(%esp), %eax
-			movl ISTATE_OFFSET_EBX(%esp), %ebx
-			movl ISTATE_OFFSET_ECX(%esp), %ecx
-			movl ISTATE_OFFSET_EDX(%esp), %edx
-			movl ISTATE_OFFSET_EBP(%esp), %ebp
-			
-			addl $(ISTATE_SOFT_SIZE + 4), %esp
-			iret
-		
-	.endif
 .endm
 
Index: kernel/arch/ia32/src/pm.c
===================================================================
--- kernel/arch/ia32/src/pm.c	(revision c15b37446cc540323e335d60ebc0166256615461)
+++ kernel/arch/ia32/src/pm.c	(revision 44c69b668c00d396162d5dd7c6d15d727c9b4a28)
@@ -206,4 +206,6 @@
 	idt_setoffset(d++, (uintptr_t) &int_62);
 	idt_setoffset(d++, (uintptr_t) &int_63);
+
+	idt_setoffset(&idt[VECTOR_SYSCALL], (uintptr_t) &int_syscall);
 }
 
