Create macros SAVEBREGS_POP_DSEAX and RESTOREBREGS_DSEAX for saving and restoring the cpu state. These are similar to the existing PUSHBREGS and POPBREGS macros.
This also fixes a bug in __farcall16 which inadvertently restored %ds in %es and vice-versa.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/entryfuncs.S | 44 ++++++++++++++++++++++++++++++++++++++++---- src/romlayout.S | 49 +++++-------------------------------------------- vgasrc/vgaentry.S | 22 ++-------------------- 3 files changed, 47 insertions(+), 68 deletions(-)
diff --git a/src/entryfuncs.S b/src/entryfuncs.S index 8438604..4e6151e 100644 --- a/src/entryfuncs.S +++ b/src/entryfuncs.S @@ -1,16 +1,17 @@ // Macros for entering C code // -// Copyright (C) 2008,2009 Kevin O'Connor kevin@koconnor.net +// Copyright (C) 2008-2014 Kevin O'Connor kevin@koconnor.net // // This file may be distributed under the terms of the GNU LGPLv3 license.
/**************************************************************** - * Entry macros + * Macros for save and restore of 'struct bregs' registers ****************************************************************/
+ // Save registers (matches struct bregs) to stack .macro PUSHBREGS - pushl %eax // Save registers (matches struct bregs) + pushl %eax pushl %ecx pushl %edx pushl %ebx @@ -21,8 +22,9 @@ pushw %ds .endm
+ // Restore registers (from struct bregs) from stack .macro POPBREGS - popw %ds // Restore registers (from struct bregs) + popw %ds popw %es popl %edi popl %esi @@ -33,6 +35,40 @@ 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. diff --git a/src/romlayout.S b/src/romlayout.S index 4ebbdee..a623138 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -151,19 +151,8 @@ __farcall16: pushw BREGS_flags(%eax) // flags pushl BREGS_code(%eax) // CS:IP
- // Load calling registers. - 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 - - // Invoke call + // Load calling registers and invoke call + RESTOREBREGS_DSEAX iretw // XXX - just do a lcalll 1: // Store flags, es, eax @@ -174,18 +163,8 @@ __farcall16: pushl %eax movw 0x08(%esp), %ds movl 0x0c(%esp), %eax - popl BREGS_eax(%eax) - popw BREGS_es(%eax) + SAVEBREGS_POP_DSEAX popw BREGS_flags(%eax) - - // Store remaining registers - 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_ds(%eax) movw %ss, %cx movw %cx, %ds // Restore %ds == %ss
@@ -508,16 +487,8 @@ irqentry_arg_extrastack: movl %eax, %ds movl StackPos, %eax subl $BREGS_size+8, %eax - popl BREGS_eax(%eax) // Backup registers - 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) + SAVEBREGS_POP_DSEAX // Save registers on extra stack popl %ecx - movw %es, BREGS_es(%eax) movl %esp, BREGS_size+0(%eax) movw %ss, BREGS_size+4(%eax) popl BREGS_code(%eax) @@ -535,17 +506,7 @@ irqentry_arg_extrastack: popw %dx pushw BREGS_flags(%eax) pushl BREGS_code(%eax) - 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 - pushw BREGS_ds(%eax) - pushl BREGS_eax(%eax) - popl %eax - popw %ds + RESTOREBREGS_DSEAX iretw
// Main entry point for interrupts with args diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S index 3c2c885..5d45380 100644 --- a/vgasrc/vgaentry.S +++ b/vgasrc/vgaentry.S @@ -113,15 +113,7 @@ entry_10_extrastack: pushl %eax movw %cs:ExtraStackSeg, %ds movl $(CONFIG_VGA_EXTRA_STACK_SIZE-BREGS_size-8), %eax - popl BREGS_eax(%eax) // Backup registers - 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) + SAVEBREGS_POP_DSEAX // Save registers on extra stack movl %esp, BREGS_size+0(%eax) movw %ss, BREGS_size+4(%eax) popl BREGS_code(%eax) @@ -139,15 +131,5 @@ entry_10_extrastack: popw %dx pushw BREGS_flags(%eax) pushl BREGS_code(%eax) - 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 - pushw BREGS_ds(%eax) - pushl BREGS_eax(%eax) - popl %eax - popw %ds + RESTOREBREGS_DSEAX iretw