Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / wuf.S
diff --git a/qemu/roms/openbios/arch/sparc32/wuf.S b/qemu/roms/openbios/arch/sparc32/wuf.S
new file mode 100644 (file)
index 0000000..853fc73
--- /dev/null
@@ -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