summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/sparc32/wuf.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/sparc32/wuf.S')
-rw-r--r--qemu/roms/openbios/arch/sparc32/wuf.S154
1 files changed, 154 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/sparc32/wuf.S b/qemu/roms/openbios/arch/sparc32/wuf.S
new file mode 100644
index 000000000..853fc7322
--- /dev/null
+++ b/qemu/roms/openbios/arch/sparc32/wuf.S
@@ -0,0 +1,154 @@
+/*
+ * Window fill (underflow) trap, based on code from Sparclinux.
+ *
+ * Copyright (C) 1995 David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+// #include <psr.h>
+// #include <asi.h>
+
+/* Reg_window offsets */
+#define RW_L0 0x00
+#define RW_L1 0x04
+#define RW_L2 0x08
+#define RW_L3 0x0c
+#define RW_L4 0x10
+#define RW_L5 0x14
+#define RW_L6 0x18
+#define RW_L7 0x1c
+#define RW_I0 0x20
+#define RW_I1 0x24
+#define RW_I2 0x28
+#define RW_I3 0x2c
+#define RW_I4 0x30
+#define RW_I5 0x34
+#define RW_I6 0x38
+#define RW_I7 0x3c
+
+/* Load a register window from the area beginning at %reg. */
+#define LOAD_WINDOW(reg) \
+ ldd [%reg + RW_L0], %l0; \
+ ldd [%reg + RW_L2], %l2; \
+ ldd [%reg + RW_L4], %l4; \
+ ldd [%reg + RW_L6], %l6; \
+ ldd [%reg + RW_I0], %i0; \
+ ldd [%reg + RW_I2], %i2; \
+ ldd [%reg + RW_I4], %i4; \
+ ldd [%reg + RW_I6], %i6;
+
+#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+/* Just like the overflow handler we define macros for registers
+ * with fixed meanings in this routine.
+ */
+#define t_psr l0
+#define t_pc l1
+#define t_npc l2
+#define t_wim l3
+/* Don't touch the above registers or else you die horribly... */
+
+/* Now macros for the available scratch registers in this routine. */
+#define twin_tmp1 l4
+#define twin_tmp2 l5
+
+ .text
+ .align 4
+
+ /* The trap entry point has executed the following:
+ *
+ * rd %psr, %l0
+ * rd %wim, %l3
+ * b fill_window_entry
+ * andcc %l0, PSR_PS, %g0
+ */
+
+ /* To get an idea of what has just happened to cause this
+ * trap take a look at this diagram:
+ *
+ * 1 2 3 4 <-- Window number
+ * ----------
+ * T O W I <-- Symbolic name
+ *
+ * O == the window that execution was in when
+ * the restore was attempted
+ *
+ * T == the trap itself has save'd us into this
+ * window
+ *
+ * W == this window is the one which is now invalid
+ * and must be made valid plus loaded from the
+ * stack
+ *
+ * I == this window will be the invalid one when we
+ * are done and return from trap if successful
+ */
+
+ /* BEGINNING OF PATCH INSTRUCTIONS */
+
+ /* On 7-window Sparc the boot code patches fnwin_patch1
+ * with the following instruction.
+ */
+ .globl fnwin_patch1_7win, fnwin_patch2_7win
+fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2
+fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1
+ /* END OF PATCH INSTRUCTIONS */
+
+
+ .globl fill_window_entry, fnwin_patch1, fnwin_patch2
+fill_window_entry:
+ /* LOCATION: Window 'T' */
+
+ /* Compute what the new %wim is going to be if we retrieve
+ * the proper window off of the stack.
+ */
+ sll %t_wim, 1, %twin_tmp1
+fnwin_patch1: srl %t_wim, 7, %twin_tmp2
+ or %twin_tmp1, %twin_tmp2, %twin_tmp1
+fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1
+
+ wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */
+
+ restore %g0, %g0, %g0 /* Restore to window 'O' */
+
+ /* Trapped from kernel, we trust that the kernel does not
+ * 'over restore' sorta speak and just grab the window
+ * from the stack and return. Easy enough.
+ */
+ /* LOCATION: Window 'O' */
+
+ restore %g0, %g0, %g0
+ WRITE_PAUSE
+
+ /* LOCATION: Window 'W' */
+
+ LOAD_WINDOW(sp) /* Load it up */
+
+ /* Spin the wheel... */
+ save %g0, %g0, %g0
+ save %g0, %g0, %g0
+ /* I'd like to buy a vowel please... */
+
+ /* LOCATION: Window 'T' */
+
+ /* Now preserve the condition codes in %psr, pause, and
+ * return from trap. This is the simplest case of all.
+ */
+ wr %t_psr, 0x0, %psr
+ WRITE_PAUSE
+
+ jmp %t_pc
+ rett %t_npc