|
|
1.1 ! root 1: /* ! 2: * Window fill (underflow) trap, based on code from Sparclinux. ! 3: * ! 4: * Copyright (C) 1995 David S. Miller ! 5: * ! 6: * This program is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU General Public License ! 8: * version 2 as published by the Free Software Foundation. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, ! 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: * GNU General Public License for more details. ! 14: * ! 15: * You should have received a copy of the GNU General Public License ! 16: * along with this program; if not, write to the Free Software ! 17: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ! 18: * MA 02110-1301, USA. ! 19: */ ! 20: ! 21: // #include <psr.h> ! 22: // #include <asi.h> ! 23: ! 24: /* Reg_window offsets */ ! 25: #define RW_L0 0x00 ! 26: #define RW_L1 0x04 ! 27: #define RW_L2 0x08 ! 28: #define RW_L3 0x0c ! 29: #define RW_L4 0x10 ! 30: #define RW_L5 0x14 ! 31: #define RW_L6 0x18 ! 32: #define RW_L7 0x1c ! 33: #define RW_I0 0x20 ! 34: #define RW_I1 0x24 ! 35: #define RW_I2 0x28 ! 36: #define RW_I3 0x2c ! 37: #define RW_I4 0x30 ! 38: #define RW_I5 0x34 ! 39: #define RW_I6 0x38 ! 40: #define RW_I7 0x3c ! 41: ! 42: /* Load a register window from the area beginning at %reg. */ ! 43: #define LOAD_WINDOW(reg) \ ! 44: ldd [%reg + RW_L0], %l0; \ ! 45: ldd [%reg + RW_L2], %l2; \ ! 46: ldd [%reg + RW_L4], %l4; \ ! 47: ldd [%reg + RW_L6], %l6; \ ! 48: ldd [%reg + RW_I0], %i0; \ ! 49: ldd [%reg + RW_I2], %i2; \ ! 50: ldd [%reg + RW_I4], %i4; \ ! 51: ldd [%reg + RW_I6], %i6; ! 52: ! 53: #define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ ! 54: ! 55: /* Just like the overflow handler we define macros for registers ! 56: * with fixed meanings in this routine. ! 57: */ ! 58: #define t_psr l0 ! 59: #define t_pc l1 ! 60: #define t_npc l2 ! 61: #define t_wim l3 ! 62: /* Don't touch the above registers or else you die horribly... */ ! 63: ! 64: /* Now macros for the available scratch registers in this routine. */ ! 65: #define twin_tmp1 l4 ! 66: #define twin_tmp2 l5 ! 67: ! 68: .text ! 69: .align 4 ! 70: ! 71: /* The trap entry point has executed the following: ! 72: * ! 73: * rd %psr, %l0 ! 74: * rd %wim, %l3 ! 75: * b fill_window_entry ! 76: * andcc %l0, PSR_PS, %g0 ! 77: */ ! 78: ! 79: /* To get an idea of what has just happened to cause this ! 80: * trap take a look at this diagram: ! 81: * ! 82: * 1 2 3 4 <-- Window number ! 83: * ---------- ! 84: * T O W I <-- Symbolic name ! 85: * ! 86: * O == the window that execution was in when ! 87: * the restore was attempted ! 88: * ! 89: * T == the trap itself has save'd us into this ! 90: * window ! 91: * ! 92: * W == this window is the one which is now invalid ! 93: * and must be made valid plus loaded from the ! 94: * stack ! 95: * ! 96: * I == this window will be the invalid one when we ! 97: * are done and return from trap if successful ! 98: */ ! 99: ! 100: /* BEGINNING OF PATCH INSTRUCTIONS */ ! 101: ! 102: /* On 7-window Sparc the boot code patches fnwin_patch1 ! 103: * with the following instruction. ! 104: */ ! 105: .globl fnwin_patch1_7win, fnwin_patch2_7win ! 106: fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2 ! 107: fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1 ! 108: /* END OF PATCH INSTRUCTIONS */ ! 109: ! 110: ! 111: .globl fill_window_entry, fnwin_patch1, fnwin_patch2 ! 112: fill_window_entry: ! 113: /* LOCATION: Window 'T' */ ! 114: ! 115: /* Compute what the new %wim is going to be if we retrieve ! 116: * the proper window off of the stack. ! 117: */ ! 118: sll %t_wim, 1, %twin_tmp1 ! 119: fnwin_patch1: srl %t_wim, 7, %twin_tmp2 ! 120: or %twin_tmp1, %twin_tmp2, %twin_tmp1 ! 121: fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1 ! 122: ! 123: wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */ ! 124: ! 125: restore %g0, %g0, %g0 /* Restore to window 'O' */ ! 126: ! 127: /* Trapped from kernel, we trust that the kernel does not ! 128: * 'over restore' sorta speak and just grab the window ! 129: * from the stack and return. Easy enough. ! 130: */ ! 131: /* LOCATION: Window 'O' */ ! 132: ! 133: restore %g0, %g0, %g0 ! 134: ! 135: /* LOCATION: Window 'W' */ ! 136: ! 137: LOAD_WINDOW(sp) /* Load it up */ ! 138: ! 139: /* Spin the wheel... */ ! 140: save %g0, %g0, %g0 ! 141: save %g0, %g0, %g0 ! 142: /* I'd like to buy a vowel please... */ ! 143: ! 144: /* LOCATION: Window 'T' */ ! 145: ! 146: /* Now preserve the condition codes in %psr, pause, and ! 147: * return from trap. This is the simplest case of all. ! 148: */ ! 149: wr %t_psr, 0x0, %psr ! 150: WRITE_PAUSE ! 151: ! 152: jmp %t_pc ! 153: rett %t_npc
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.