| // Macros for entering C code |
| // |
| // Copyright (C) 2008-2014 Kevin O'Connor <kevin@koconnor.net> |
| // |
| // 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 |