[SeaBIOS] [PATCH 2/4] Create assembler macros for saving and restoring 'struct bregs'
Kevin O'Connor
kevin at koconnor.net
Tue Oct 21 20:53:43 CEST 2014
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 at 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 at koconnor.net>
+// Copyright (C) 2008-2014 Kevin O'Connor <kevin at 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
--
1.9.3
More information about the SeaBIOS
mailing list