From 9e80202352dd49bdd9e67b8b906d86f058431505 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineering.com>
Date: Sat, 11 May 2019 15:12:49 -0500
Subject: Initial import of abandoned HQEMU version 2.5.2

---
 src/roms/openbios/arch/x86/entry.S | 315 +++++++++++++++++++++++++++++++++++++
 1 file changed, 315 insertions(+)
 create mode 100644 src/roms/openbios/arch/x86/entry.S

(limited to 'src/roms/openbios/arch/x86/entry.S')

diff --git a/src/roms/openbios/arch/x86/entry.S b/src/roms/openbios/arch/x86/entry.S
new file mode 100644
index 0000000..8f1e42e
--- /dev/null
+++ b/src/roms/openbios/arch/x86/entry.S
@@ -0,0 +1,315 @@
+	.globl	entry, __switch_context, __exit_context, halt, init_exceptions
+
+	.text
+	.align	4
+
+/*
+ * Entry point
+ * We start execution from here.
+ * It is assumed that CPU is in 32-bit protected mode and
+ * all segments are 4GB and base zero (flat model).
+ */
+entry:
+	/* Save boot context and switch to our main context.
+	 * Main context is statically defined in C.
+	 */
+	pushl	%cs
+	call	__switch_context
+
+	/* We get here when the main context switches back to
+	 * the boot context.
+	 * Return to previous bootloader.
+	 */
+	ret
+
+/*
+ * Switch execution context
+ * This saves registers, segments, and GDT in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ *
+ * Call this routine with lcall or pushl %cs; call.
+ */
+__switch_context:
+	/* Save everything in current stack */
+	pushfl		    /* 56 */
+	pushl	%ds	    /* 52 */
+	pushl	%es	    /* 48 */
+	pushl	%fs	    /* 44 */
+	pushl	%gs	    /* 40 */
+	pushal		    /* 8 */
+	subl	$8, %esp
+	movw	%ss, (%esp) /* 0 */
+	sgdt	2(%esp)	    /* 2 */
+
+#if 0
+	/* Swap %cs and %eip on the stack, so lret will work */
+	movl	60(%esp), %eax
+	xchgl	%eax, 64(%esp)
+	movl	%eax, 60(%esp)
+#endif
+
+	/* At this point we don't know if we are on flat segment
+	 * or relocated. So compute the address offset from %eip.
+	 * Assuming CS.base==DS.base==SS.base.
+	 */
+	call	1f
+1:	popl	%ebx
+	subl	$1b, %ebx
+
+	/* Interrupts are not allowed... */
+	cli
+
+	/* Current context pointer is our stack pointer */
+	movl	%esp, %esi
+
+	/* Normalize the ctx pointer */
+	subl	%ebx, %esi
+
+	/* Swap it with new value */
+	xchgl	%esi, __context(%ebx)
+
+	/* Adjust new ctx pointer for current address offset */
+	addl	%ebx, %esi
+
+	/* Load new %ss and %esp to temporary */
+	movzwl	(%esi), %edx
+	movl	20(%esi), %eax
+
+	/* Load new GDT */
+	lgdt	2(%esi)
+
+	/* Load new stack segment with new GDT */
+	movl	%edx, %ss
+
+	/* Set new stack pointer, but we have to adjust it because
+	 * pushal saves %esp value before pushal, and we want the value
+	 * after pushal.
+	 */
+	leal	-32(%eax), %esp
+
+	/* Load the rest from new stack */
+	popal
+	popl	%gs
+	popl	%fs
+	popl	%es
+	popl	%ds
+	popfl
+
+	/* Finally, load new %cs and %eip */
+	lret
+
+__exit_context:
+	/* Get back to the original context */
+	pushl	%cs
+	call	__switch_context
+
+	/* We get here if the other context attempt to switch to this
+	 * dead context. This should not happen. */
+
+halt:
+	cli
+	hlt
+	jmp	halt
+
+/*
+ * initialize exception handler. All exceptions end up in the same
+ * C function.
+ */
+
+init_exceptions:
+	pushl	%ebx
+	pushl	%edi
+
+        /* Initialize the Interrupt Descriptor table */
+        leal    _idt, %edi
+        leal    vec0, %ebx
+        movl    $(0x08 << 16), %eax     /* cs selector */
+
+1:      movw    %bx, %ax
+        movl    %ebx, %edx
+        movw    $0x8E00, %dx            /* Interrupt gate - dpl=0, present */
+        movl    %eax, 0(%edi)
+        movl    %edx, 4(%edi)
+        addl    $6, %ebx
+        addl    $8, %edi
+        cmpl    $_idt_end, %edi
+        jne     1b
+
+        /* Load the Interrupt descriptor table */
+        lidt    idtarg
+
+	movl 	$0, %eax
+	popl	%edi
+	popl	%ebx
+	ret
+
+vec0:
+        pushl   $0 /* error code */
+        pushl   $0 /* vector */
+        jmp int_hand
+vec1:
+        pushl   $0 /* error code */
+        pushl   $1 /* vector */
+        jmp int_hand
+
+vec2:
+        pushl   $0 /* error code */
+        pushl   $2 /* vector */
+        jmp int_hand
+
+vec3:
+        pushl   $0 /* error code */
+        pushl   $3 /* vector */
+        jmp     int_hand
+
+vec4:
+        pushl   $0 /* error code */
+        pushl   $4 /* vector */
+        jmp     int_hand
+
+vec5:
+        pushl   $0 /* error code */
+        pushl   $5 /* vector */
+        jmp     int_hand
+
+vec6:
+        pushl   $0 /* error code */
+        pushl   $6 /* vector */
+        jmp     int_hand
+vec7:
+        pushl   $0 /* error code */
+        pushl   $7 /* vector */
+        jmp     int_hand
+
+vec8:
+        /* error code */
+        pushl   $8 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec9:
+        pushl   $0 /* error code */
+        pushl   $9 /* vector */
+        jmp int_hand
+
+vec10:
+        /* error code */
+        pushl   $10 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec11:
+        /* error code */
+        pushl   $11 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec12:
+        /* error code */
+        pushl   $12 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec13:
+        /* error code */
+        pushl   $13 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec14:
+        /* error code */
+        pushl   $14 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec15:
+        pushl   $0 /* error code */
+        pushl   $15 /* vector */
+        jmp     int_hand
+
+vec16:
+        pushl   $0 /* error code */
+        pushl   $16 /* vector */
+        jmp     int_hand
+
+vec17:
+        /* error code */
+        pushl   $17 /* vector */
+        jmp     int_hand
+        .word   0x9090
+
+vec18:
+        pushl   $0 /* error code */
+        pushl   $18 /* vector */
+        jmp     int_hand
+
+vec19:
+        pushl   $0 /* error code */
+        pushl   $19 /* vector */
+        jmp     int_hand
+
+__divide_error:
+        pushl   $0 /* error code */
+        pushl   $20 /* vector */
+        jmp     int_hand
+        .global __divide_error
+
+int_hand:
+        /* At this point on the stack there is:
+         *  0(%esp) vector
+         *  4(%esp) error code
+         *  8(%esp) eip
+         * 12(%esp) cs
+         * 16(%esp) eflags
+         */
+        pushl   %edi
+        pushl   %esi
+        pushl   %ebp
+        /* Original stack pointer */
+        leal    32(%esp), %ebp
+        pushl   %ebp
+        pushl   %ebx
+        pushl   %edx
+        pushl   %ecx
+        pushl   %eax
+
+        pushl   %esp    /* Pointer to structure on the stack */
+
+        call    x86_exception
+        pop     %eax    /* Drop the pointer */
+
+        popl    %eax
+        popl    %ecx
+        popl    %edx
+        popl    %ebx
+        popl    %ebp /* Ignore saved %esp value */
+        popl    %ebp
+        popl    %esi
+        popl    %edi
+
+        addl    $8, %esp /* pop of the vector and error code */
+
+        iret
+
+idtarg:
+        .word   _idt_end - _idt - 1     /* limit */
+        .long   _idt
+        .word   0
+_idt:
+        .fill   20, 8, 0        # idt is unitiailzed
+_idt_end:
+
+        .globl  arch_nvram_size, arch_nvram_get, arch_nvram_put
+arch_nvram_size:
+        xor     %eax, %eax
+        ret
+
+arch_nvram_get:
+        ret
+
+arch_nvram_put:
+        ret
-- 
cgit v1.1