| 1 | /* |
| 2 | * SPARC specific CPU ABI and functions for linux-user |
| 3 | * |
| 4 | * Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> |
| 5 | * Copyright (C) 2003-2005 Fabrice Bellard |
| 6 | * |
| 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation; either |
| 10 | * version 2.1 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
| 18 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| 19 | */ |
| 20 | #ifndef SPARC_TARGET_CPU_H |
| 21 | #define SPARC_TARGET_CPU_H |
| 22 | |
| 23 | #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) |
| 24 | # define TARGET_STACK_BIAS 2047 |
| 25 | #else |
| 26 | # define TARGET_STACK_BIAS 0 |
| 27 | #endif |
| 28 | |
| 29 | static void set_syscall_C(CPUSPARCState *env, bool val) |
| 30 | { |
| 31 | #ifndef TARGET_SPARC64 |
| 32 | env->icc_C = val; |
| 33 | #elif defined(TARGET_ABI32) |
| 34 | env->icc_C = (uint64_t)val << 32; |
| 35 | #else |
| 36 | env->xcc_C = val; |
| 37 | #endif |
| 38 | } |
| 39 | |
| 40 | static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp, |
| 41 | unsigned flags) |
| 42 | { |
| 43 | /* |
| 44 | * After cpu_copy, env->regwptr is pointing into the old env. |
| 45 | * Update the new cpu to use its own register window. |
| 46 | */ |
| 47 | env->regwptr = env->regbase + (env->cwp * 16); |
| 48 | |
| 49 | if (newsp) { |
| 50 | /* When changing stacks, do it with clean register windows. */ |
| 51 | #ifdef TARGET_SPARC64 |
| 52 | env->cansave = env->nwindows - 2; |
| 53 | env->cleanwin = env->nwindows - 2; |
| 54 | env->canrestore = 0; |
| 55 | #else |
| 56 | env->wim = 1 << env->cwp; |
| 57 | #endif |
| 58 | /* ??? The kernel appears to copy one stack frame to the new stack. */ |
| 59 | /* ??? The kernel force aligns the new stack. */ |
| 60 | /* Userspace provides a biased stack pointer value. */ |
| 61 | env->regwptr[WREG_SP] = newsp; |
| 62 | } |
| 63 | |
| 64 | if (flags & CLONE_VM) { |
| 65 | /* |
| 66 | * Syscall return for clone child: %o0 = 0 and clear CF since this |
| 67 | * counts as a success return value. Advance the PC past the syscall. |
| 68 | * For fork child, all of this happens in cpu_loop, and we must not |
| 69 | * do the pc advance twice. |
| 70 | */ |
| 71 | env->regwptr[WREG_O0] = 0; |
| 72 | set_syscall_C(env, 0); |
| 73 | env->pc = env->npc; |
| 74 | env->npc = env->npc + 4; |
| 75 | } |
| 76 | |
| 77 | /* Set the second return value for the child: %o1 = 1. */ |
| 78 | env->regwptr[WREG_O1] = 1; |
| 79 | } |
| 80 | |
| 81 | static inline void cpu_clone_regs_parent(CPUSPARCState *env, unsigned flags) |
| 82 | { |
| 83 | /* Set the second return value for the parent: %o1 = 0. */ |
| 84 | env->regwptr[WREG_O1] = 0; |
| 85 | } |
| 86 | |
| 87 | static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) |
| 88 | { |
| 89 | env->gregs[7] = newtls; |
| 90 | } |
| 91 | |
| 92 | static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) |
| 93 | { |
| 94 | return state->regwptr[WREG_SP] + TARGET_STACK_BIAS; |
| 95 | } |
| 96 | |
| 97 | #endif |