[c4808ca] | 1 | /* |
---|
| 2 | * window.s |
---|
| 3 | * |
---|
[359e537] | 4 | * This file contains the register window management routines for the |
---|
[c4808ca] | 5 | * SPARC architecture. Trap handlers for the following capabilities |
---|
| 6 | * are included in this file: |
---|
| 7 | * |
---|
| 8 | * + Window Overflow |
---|
| 9 | * + Window Underflow |
---|
| 10 | * + Flushing All Windows |
---|
[359e537] | 11 | * |
---|
[c4808ca] | 12 | * COPYRIGHT: |
---|
| 13 | * |
---|
[359e537] | 14 | * This file includes the window overflow and underflow handlers from |
---|
| 15 | * the file srt0.s provided with the binary distribution of the SPARC |
---|
| 16 | * Instruction Simulator (SIS) found at |
---|
[c4808ca] | 17 | * ftp://ftp.estec.esa.nl/pub/ws/wsd/erc32. |
---|
| 18 | * |
---|
| 19 | * COPYRIGHT (c) 1995. European Space Agency. |
---|
| 20 | * |
---|
| 21 | * This terms of the RTEMS license apply to this file. |
---|
| 22 | * |
---|
| 23 | * $Id$ |
---|
| 24 | */ |
---|
| 25 | |
---|
[173fd7c] | 26 | #include <rtems/asm.h> |
---|
[c4808ca] | 27 | |
---|
| 28 | .seg "text" |
---|
| 29 | /* |
---|
| 30 | * Window overflow trap handler. |
---|
| 31 | * |
---|
| 32 | * On entry: |
---|
| 33 | * |
---|
| 34 | * l0 = psr (from trap table) |
---|
| 35 | * l1 = pc |
---|
| 36 | * l2 = npc |
---|
| 37 | */ |
---|
| 38 | |
---|
| 39 | PUBLIC(window_overflow_trap_handler) |
---|
| 40 | |
---|
| 41 | SYM(window_overflow_trap_handler): |
---|
| 42 | |
---|
| 43 | /* |
---|
[359e537] | 44 | * Calculate new WIM by "rotating" the valid bits in the WIM right |
---|
[c4808ca] | 45 | * by one position. The following shows how the bits move for a SPARC |
---|
| 46 | * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. |
---|
| 47 | * |
---|
| 48 | * OLD WIM = 76543210 |
---|
| 49 | * NEW WIM = 07654321 |
---|
| 50 | * |
---|
| 51 | * NOTE: New WIM must be stored in a global register since the |
---|
[359e537] | 52 | * "save" instruction just prior to the load of the wim |
---|
[c4808ca] | 53 | * register will result in the local register set changing. |
---|
| 54 | */ |
---|
| 55 | |
---|
| 56 | mov %wim, %l3 ! l3 = WIM |
---|
| 57 | mov %g1, %l7 ! save g1 |
---|
| 58 | srl %l3, 1, %g1 ! g1 = WIM >> 1 |
---|
| 59 | sll %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4 |
---|
| 60 | ! l4 = WIM << (Number Windows - 1) |
---|
[359e537] | 61 | or %l4, %g1, %g1 ! g1 = (WIM >> 1) | |
---|
[c4808ca] | 62 | ! (WIM << (Number Windows - 1)) |
---|
| 63 | |
---|
| 64 | save ! Get into window to be saved. |
---|
| 65 | mov %g1, %wim ! load new WIM |
---|
| 66 | nop; nop; nop ! 3 slot delay |
---|
| 67 | std %l0, [%sp + 0x00] ! save local register set |
---|
| 68 | std %l2, [%sp + 0x08] |
---|
| 69 | std %l4, [%sp + 0x10] |
---|
| 70 | std %l6, [%sp + 0x18] |
---|
| 71 | std %i0, [%sp + 0x20] ! save input register set |
---|
| 72 | std %i2, [%sp + 0x28] |
---|
| 73 | std %i4, [%sp + 0x30] |
---|
| 74 | std %i6, [%sp + 0x38] |
---|
| 75 | restore ! Go back to trap window. |
---|
| 76 | mov %l7, %g1 ! restore g1 |
---|
| 77 | jmp %l1 ! Re-execute save. |
---|
| 78 | rett %l2 |
---|
| 79 | |
---|
| 80 | /* |
---|
| 81 | * Window underflow trap handler. |
---|
| 82 | * |
---|
| 83 | * On entry: |
---|
| 84 | * |
---|
| 85 | * l0 = psr (from trap table) |
---|
| 86 | * l1 = pc |
---|
| 87 | * l2 = npc |
---|
| 88 | */ |
---|
| 89 | |
---|
| 90 | PUBLIC(window_underflow_trap_handler) |
---|
| 91 | |
---|
| 92 | SYM(window_underflow_trap_handler): |
---|
| 93 | |
---|
| 94 | /* |
---|
[359e537] | 95 | * Calculate new WIM by "rotating" the valid bits in the WIM left |
---|
[c4808ca] | 96 | * by one position. The following shows how the bits move for a SPARC |
---|
| 97 | * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. |
---|
| 98 | * |
---|
| 99 | * OLD WIM = 76543210 |
---|
| 100 | * NEW WIM = 07654321 |
---|
| 101 | * |
---|
| 102 | * NOTE: New WIM must be stored in a global register since the |
---|
[359e537] | 103 | * "save" instruction just prior to the load of the wim |
---|
[c4808ca] | 104 | * register will result in the local register set changing. |
---|
| 105 | */ |
---|
| 106 | |
---|
| 107 | mov %wim, %l3 ! Calculate new WIM |
---|
| 108 | sll %l3, 1, %l4 ! l4 = WIM << 1 |
---|
| 109 | srl %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1, %l5 |
---|
| 110 | ! l5 = WIM >> (Number Windows-1) |
---|
| 111 | or %l5, %l4, %l5 ! l5 = (WIM << 1) | |
---|
| 112 | ! (WIM >> (Number Windows-1)) |
---|
| 113 | mov %l5, %wim ! load the new WIM |
---|
| 114 | nop; nop; nop |
---|
| 115 | restore ! Two restores to get into the |
---|
| 116 | restore ! window to restore |
---|
| 117 | ldd [%sp + 0x00], %l0 ! First the local register set |
---|
| 118 | ldd [%sp + 0x08], %l2 |
---|
| 119 | ldd [%sp + 0x10], %l4 |
---|
| 120 | ldd [%sp + 0x18], %l6 |
---|
| 121 | ldd [%sp + 0x20], %i0 ! Then the input registers |
---|
| 122 | ldd [%sp + 0x28], %i2 |
---|
| 123 | ldd [%sp + 0x30], %i4 |
---|
| 124 | ldd [%sp + 0x38], %i6 |
---|
| 125 | save ! Get back to the trap window. |
---|
| 126 | save |
---|
| 127 | jmp %l1 ! Re-execute restore. |
---|
| 128 | rett %l2 |
---|
| 129 | |
---|
| 130 | /* |
---|
| 131 | * Flush All Windows trap handler. |
---|
| 132 | * |
---|
| 133 | * Flush all windows with valid contents except the current one |
---|
| 134 | * and the one we will be returning to. |
---|
| 135 | * |
---|
| 136 | * In examining the set register windows, one may logically divide |
---|
| 137 | * the windows into sets (some of which may be empty) based on their |
---|
| 138 | * current status: |
---|
| 139 | * |
---|
| 140 | * + current (i.e. in use), |
---|
| 141 | * + used (i.e. a restore would not trap) |
---|
| 142 | * + invalid (i.e. 1 in corresponding bit in WIM) |
---|
| 143 | * + unused |
---|
| 144 | * |
---|
| 145 | * Either the used or unused set of windows may be empty. |
---|
| 146 | * |
---|
| 147 | * NOTE: We assume only one bit is set in the WIM at a time. |
---|
| 148 | * |
---|
| 149 | * Given a CWP of 5 and a WIM of 0x1, the registers are divided |
---|
| 150 | * into sets as follows: |
---|
| 151 | * |
---|
| 152 | * + 0 - invalid |
---|
| 153 | * + 1-4 - unused |
---|
| 154 | * + 5 - current |
---|
| 155 | * + 6-7 - used |
---|
| 156 | * |
---|
| 157 | * In this case, we only would save the used windows which we |
---|
| 158 | * will not be returning to -- 6. |
---|
| 159 | * |
---|
| 160 | * Register Usage while saving the windows: |
---|
| 161 | * g1 = current PSR |
---|
| 162 | * g2 = current wim |
---|
| 163 | * g3 = CWP |
---|
| 164 | * g4 = wim scratch |
---|
| 165 | * g5 = scratch |
---|
| 166 | * |
---|
| 167 | * On entry: |
---|
| 168 | * |
---|
| 169 | * l0 = psr (from trap table) |
---|
| 170 | * l1 = pc |
---|
| 171 | * l2 = npc |
---|
| 172 | */ |
---|
[359e537] | 173 | |
---|
[c4808ca] | 174 | PUBLIC(window_flush_trap_handler) |
---|
[359e537] | 175 | |
---|
[c4808ca] | 176 | SYM(window_flush_trap_handler): |
---|
| 177 | /* |
---|
| 178 | * Save the global registers we will be using |
---|
| 179 | */ |
---|
| 180 | |
---|
| 181 | mov %g1, %l3 |
---|
| 182 | mov %g2, %l4 |
---|
| 183 | mov %g3, %l5 |
---|
| 184 | mov %g4, %l6 |
---|
| 185 | mov %g5, %l7 |
---|
| 186 | |
---|
| 187 | mov %l0, %g1 ! g1 = psr |
---|
| 188 | mov %wim, %g2 ! g2 = wim |
---|
| 189 | and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP |
---|
| 190 | |
---|
| 191 | add %g3, 1, %g5 ! g5 = CWP + 1 |
---|
| 192 | and %g5, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g5 |
---|
| 193 | |
---|
| 194 | mov 1, %g4 |
---|
| 195 | sll %g4, %g5, %g4 ! g4 = WIM mask for CWP+1 invalid |
---|
| 196 | |
---|
| 197 | restore ! go back one register window |
---|
[359e537] | 198 | |
---|
[c4808ca] | 199 | save_frame_loop: |
---|
| 200 | sll %g4, 1, %g5 ! rotate the "wim" left 1 |
---|
| 201 | srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 |
---|
| 202 | or %g4, %g5, %g4 ! g4 = wim if we do one restore |
---|
[359e537] | 203 | |
---|
[c4808ca] | 204 | /* |
---|
| 205 | * If a restore would not underflow, then continue. |
---|
| 206 | */ |
---|
[359e537] | 207 | |
---|
[c4808ca] | 208 | andcc %g4, %g2, %g0 ! Any windows to flush? |
---|
| 209 | bnz done_flushing ! No, then continue |
---|
| 210 | nop |
---|
[359e537] | 211 | |
---|
[c4808ca] | 212 | restore ! back one window |
---|
[359e537] | 213 | |
---|
[c4808ca] | 214 | /* |
---|
| 215 | * Now save the window just as if we overflowed to it. |
---|
| 216 | */ |
---|
[359e537] | 217 | |
---|
[c4808ca] | 218 | std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] |
---|
| 219 | std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] |
---|
| 220 | std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] |
---|
| 221 | std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] |
---|
[359e537] | 222 | |
---|
[c4808ca] | 223 | std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] |
---|
| 224 | std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] |
---|
| 225 | std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] |
---|
| 226 | std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] |
---|
[359e537] | 227 | |
---|
[c4808ca] | 228 | ba save_frame_loop |
---|
| 229 | nop |
---|
[359e537] | 230 | |
---|
[c4808ca] | 231 | done_flushing: |
---|
[359e537] | 232 | |
---|
[c4808ca] | 233 | add %g3, 2, %g3 ! calculate desired WIM |
---|
| 234 | and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3 |
---|
| 235 | mov 1, %g4 |
---|
| 236 | sll %g4, %g3, %g4 ! g4 = new WIM |
---|
| 237 | mov %g4, %wim |
---|
[359e537] | 238 | |
---|
[c4808ca] | 239 | mov %g1, %psr ! restore PSR |
---|
| 240 | nop |
---|
| 241 | nop |
---|
| 242 | nop |
---|
| 243 | |
---|
| 244 | /* |
---|
| 245 | * Restore the global registers we used |
---|
| 246 | */ |
---|
| 247 | |
---|
| 248 | mov %l3, %g1 |
---|
| 249 | mov %l4, %g2 |
---|
| 250 | mov %l5, %g3 |
---|
| 251 | mov %l6, %g4 |
---|
| 252 | mov %l7, %g5 |
---|
| 253 | |
---|
| 254 | jmpl %l2, %g0 |
---|
| 255 | rett %l2 + 4 |
---|
| 256 | |
---|
| 257 | /* end of file */ |
---|