// Macros for entering C code // // Copyright (C) 2008-2014 Kevin O'Connor // // This file may be distributed under the terms of the GNU LGPLv3 license. /**************************************************************** * Macros for save and restore of 'struct bregs' registers ****************************************************************/ #define PUSHBREGS_size 32 // Save registers (matches struct bregs) to stack .macro PUSHBREGS pushl %eax pushl %ecx pushl %edx pushl %ebx pushl %ebp pushl %esi pushl %edi pushw %es pushw %ds .endm // Restore registers (from struct bregs) from stack .macro POPBREGS popw %ds popw %es popl %edi popl %esi popl %ebp popl %ebx popl %edx popl %ecx popl %eax .endm // Save registers to struct bregs at %ds:%eax. The caller // should "pushw %ds ; pushl %eax" prior to calling - this macro // will pop them off. .macro SAVEBREGS_POP_DSEAX popl BREGS_eax(%eax) popw BREGS_ds(%eax) movl %edi, BREGS_edi(%eax) movl %esi, BREGS_esi(%eax) movl %ebp, BREGS_ebp(%eax) movl %ebx, BREGS_ebx(%eax) movl %edx, BREGS_edx(%eax) movl %ecx, BREGS_ecx(%eax) movw %es, BREGS_es(%eax) .endm // Restore registers from struct bregs at %ds:%eax .macro RESTOREBREGS_DSEAX movl BREGS_edi(%eax), %edi movl BREGS_esi(%eax), %esi movl BREGS_ebp(%eax), %ebp movl BREGS_ebx(%eax), %ebx movl BREGS_edx(%eax), %edx movl BREGS_ecx(%eax), %ecx movw BREGS_es(%eax), %es pushl BREGS_eax(%eax) movw BREGS_ds(%eax), %ds popl %eax .endm /**************************************************************** * Entry macros ****************************************************************/ // Call a C function - this does the minimal work necessary to // call into C. It sets up %ds, backs up %es, and backs up // those registers that are call clobbered by the C compiler. .macro ENTRY cfunc cli // In case something far-calls instead of using "int" cld pushl %eax // Save registers clobbered by C code pushl %ecx pushl %edx pushw %es pushw %ds movw %ss, %ax // Move %ss to %ds movw %ax, %ds pushl %esp // Backup %esp, then clear high bits movzwl %sp, %esp calll \cfunc popl %esp // Restore %esp (including high bits) popw %ds // Restore registers saved above popw %es popl %edx popl %ecx popl %eax .endm // Call a C function with current register list as an // argument. This backs up the registers and sets %eax // to point to the backup. On return, the registers are // restored from the structure. .macro ENTRY_ARG cfunc cli cld PUSHBREGS movw %ss, %ax // Move %ss to %ds movw %ax, %ds movl %esp, %ebx // Backup %esp, then zero high bits movzwl %sp, %esp movl %esp, %eax // First arg is pointer to struct bregs calll \cfunc movl %ebx, %esp // Restore %esp (including high bits) POPBREGS .endm // As above, but get calling function from stack. .macro ENTRY_ARG_ST cli cld pushl %ecx pushl %edx pushl %ebx pushl %ebp pushl %esi pushl %edi pushw %es pushw %ds movw %ss, %cx // Move %ss to %ds movw %cx, %ds movl %esp, %ebx // Backup %esp, then zero high bits movzwl %sp, %esp movl 28(%esp), %ecx // Get calling function movl %eax, 28(%esp) // Save %eax movl %esp, %eax // First arg is pointer to struct bregs calll *%ecx movl %ebx, %esp // Restore %esp (including high bits) POPBREGS .endm // Same as ENTRY_ARG, but don't mangle %esp .macro ENTRY_ARG_ESP cfunc cli cld PUSHBREGS movw %ss, %ax // Move %ss to %ds movw %ax, %ds movl %esp, %eax // First arg is pointer to struct bregs calll \cfunc POPBREGS .endm // Reset stack, transition to 32bit mode, and call a C function. .macro ENTRY_INTO32 cfunc xorw %dx, %dx movw %dx, %ss movl $ BUILD_STACK_ADDR , %esp movl $ \cfunc , %edx jmp transition32 .endm // Declare a function .macro DECLFUNC func .section .text.asm.\func .global \func .endm