| /* |
| * Save/restore CPU state macros |
| * |
| * Copyright (C) 2016 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk>) |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * version 2 |
| * |
| */ |
| |
| #include "autoconf.h" |
| |
| #define STACKFRAME_SZ 0x60 |
| |
| /* These are just handy. */ |
| #define _SV save %sp, -STACKFRAME_SZ, %sp |
| #define _RS restore |
| |
| #define FLUSH_ALL_KERNEL_WINDOWS \ |
| _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ |
| _RS; _RS; _RS; _RS; _RS; _RS; _RS; |
| |
| |
| #define SAVE_CPU_GENERAL_STATE(type) \ |
| /* Save general state into context at %g1 */ \ |
| rd %psr, %g4; \ |
| st %g4, [%g1]; \ |
| rd %wim, %g4; \ |
| st %g4, [%g1 + 0x4]; |
| |
| #define SAVE_CPU_WINDOW_STATE(type) \ |
| /* Save window state into context at %g1 */ \ |
| st %o0, [%g1 + 0x30]; \ |
| st %o1, [%g1 + 0x34]; \ |
| st %o2, [%g1 + 0x38]; \ |
| st %o3, [%g1 + 0x3c]; \ |
| st %o4, [%g1 + 0x40]; \ |
| st %o5, [%g1 + 0x44]; \ |
| st %o6, [%g1 + 0x48]; \ |
| st %o7, [%g1 + 0x4c]; \ |
| \ |
| set nwindows, %g6; \ |
| ld [%g6], %g6; /* nwindows */ \ |
| mov %g6, %g5; \ |
| sub %g5, 1, %g5; /* mask */ \ |
| \ |
| rd %psr, %g4; \ |
| and %g4, %g5, %g4; /* window */ \ |
| \ |
| rd %psr, %g3; \ |
| srl %g3, 5, %g3; \ |
| sll %g3, 5, %g3; /* psr hi */ \ |
| \ |
| mov %g1, %g2; \ |
| add %g2, 0x50, %g2; \ |
| \ |
| save_cpu_window_##type: \ |
| mov %g3, %g7; \ |
| or %g7, %g4, %g7; \ |
| wr %g7, %psr; \ |
| \ |
| st %l0, [%g2]; \ |
| st %l1, [%g2 + 0x4]; \ |
| st %l2, [%g2 + 0x8]; \ |
| st %l3, [%g2 + 0xc]; \ |
| st %l4, [%g2 + 0x10]; \ |
| st %l5, [%g2 + 0x14]; \ |
| st %l6, [%g2 + 0x18]; \ |
| st %l7, [%g2 + 0x1c]; \ |
| st %i0, [%g2 + 0x20]; \ |
| st %i1, [%g2 + 0x24]; \ |
| st %i2, [%g2 + 0x28]; \ |
| st %i3, [%g2 + 0x2c]; \ |
| st %i4, [%g2 + 0x30]; \ |
| st %i5, [%g2 + 0x34]; \ |
| st %i6, [%g2 + 0x38]; \ |
| st %i7, [%g2 + 0x3c]; \ |
| dec %g4; \ |
| and %g4, %g5, %g4; \ |
| subcc %g6, 1, %g6; \ |
| bne save_cpu_window_##type; \ |
| add %g2, 0x40, %g2; \ |
| \ |
| /* Get back to the correct window */ \ |
| ld [%g1], %g2; \ |
| wr %g2, %psr; |
| |
| #define SAVE_CPU_STATE(type) \ |
| SAVE_CPU_GENERAL_STATE(type); \ |
| SAVE_CPU_WINDOW_STATE(type); |
| |
| |
| #define RESTORE_CPU_GENERAL_STATE(type) \ |
| /* Restore window state from context at %g1 */ \ |
| ld [%g1], %g2; \ |
| wr %g2, %psr; \ |
| ld [%g1 + 0x4], %g2; \ |
| wr %g2, %wim; |
| |
| #define RESTORE_CPU_WINDOW_STATE(type) \ |
| /* Restore window state from context at %g1 */ \ |
| set nwindows, %g6; \ |
| ld [%g6], %g6; /* nwindows */ \ |
| mov %g6, %g5; \ |
| sub %g5, 1, %g5; /* mask */ \ |
| \ |
| rd %psr, %g4; \ |
| and %g4, %g5, %g4; /* window */ \ |
| \ |
| rd %psr, %g3; \ |
| srl %g3, 5, %g3; \ |
| sll %g3, 5, %g3; /* psr hi */ \ |
| \ |
| mov %g1, %g2; \ |
| add %g2, 0x50, %g2; \ |
| \ |
| restore_cpu_window_##type: \ |
| mov %g3, %g7; \ |
| or %g7, %g4, %g7; \ |
| wr %g7, %psr; \ |
| \ |
| ld [%g2], %l0; \ |
| ld [%g2 + 0x4], %l1; \ |
| ld [%g2 + 0x8], %l2; \ |
| ld [%g2 + 0xc], %l3; \ |
| ld [%g2 + 0x10], %l4; \ |
| ld [%g2 + 0x14], %l5; \ |
| ld [%g2 + 0x18], %l6; \ |
| ld [%g2 + 0x1c], %l7; \ |
| ld [%g2 + 0x20], %i0; \ |
| ld [%g2 + 0x24], %i1; \ |
| ld [%g2 + 0x28], %i2; \ |
| ld [%g2 + 0x2c], %i3; \ |
| ld [%g2 + 0x30], %i4; \ |
| ld [%g2 + 0x34], %i5; \ |
| ld [%g2 + 0x38], %i6; \ |
| ld [%g2 + 0x3c], %i7; \ |
| dec %g4; \ |
| and %g4, %g5, %g4; \ |
| subcc %g6, 1, %g6; \ |
| bne restore_cpu_window_##type; \ |
| add %g2, 0x40, %g2; \ |
| \ |
| /* Get back to the correct window */ \ |
| ld [%g1], %g2; \ |
| wr %g2, %psr; \ |
| \ |
| ld [%g1 + 0x30], %o0; \ |
| ld [%g1 + 0x34], %o1; \ |
| ld [%g1 + 0x38], %o2; \ |
| ld [%g1 + 0x3c], %o3; \ |
| ld [%g1 + 0x40], %o4; \ |
| ld [%g1 + 0x44], %o5; \ |
| ld [%g1 + 0x48], %o6; \ |
| ld [%g1 + 0x4c], %o7; |
| |
| #define RESTORE_CPU_STATE(type) \ |
| RESTORE_CPU_GENERAL_STATE(type); \ |
| RESTORE_CPU_WINDOW_STATE(type); |