uwx_context.c revision 115013
1/* 2 * Copyright (c) 2002,2003 Hewlett-Packard Company 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23#include "uwx_env.h" 24#include "uwx_context.h" 25#include "uwx_scoreboard.h" 26#include "uwx_trace.h" 27 28int uwx_init_context( 29 struct uwx_env *env, 30 uint64_t ip, 31 uint64_t sp, 32 uint64_t bsp, 33 uint64_t cfm) 34{ 35 int i; 36 37 if (env == 0) 38 return UWX_ERR_NOENV; 39 40 env->context.special[UWX_REG_IP] = ip; 41 env->context.special[UWX_REG_SP] = sp; 42 env->context.special[UWX_REG_BSP] = bsp; 43 env->context.special[UWX_REG_CFM] = cfm; 44 for (i = UWX_REG_RP; i < NSPECIALREG; i++) 45 env->context.special[i] = 0; 46 for (i = 0; i < NPRESERVEDGR; i++) 47 env->context.gr[i] = 0; 48 env->context.valid_regs = VALID_BASIC4; 49 env->rstate = 0; 50 (void)uwx_init_history(env); 51 return UWX_OK; 52} 53 54int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp) 55{ 56 int status; 57 int sor; 58 int rrb_gr; 59 uint64_t bsp; 60 int n; 61 62 if (env == 0) 63 return UWX_ERR_NOENV; 64 65 status = UWX_OK; 66 67 if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid))) 68 *valp = env->context.special[regid]; 69 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 70 (env->context.valid_regs & 71 (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) 72 *valp = env->context.gr[regid - UWX_REG_GR(4)]; 73 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 74 if (env->copyin == 0) 75 return UWX_ERR_NOCALLBACKS; 76 bsp = env->context.special[UWX_REG_BSP]; 77 TRACE_C_GET_REG(regid, bsp) 78 regid -= UWX_REG_GR(32); 79 sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 80 rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 81 if (sor != 0 && rrb_gr != 0 && regid < sor) { 82 TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor) 83 regid = (regid + rrb_gr) % sor; 84 } 85 bsp = uwx_add_to_bsp(bsp, regid); 86 n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp, 87 bsp, DWORDSZ, env->cb_token); 88 if (n != DWORDSZ) 89 status = UWX_ERR_COPYIN_RSTK; 90 } 91 else if (regid == UWX_REG_GR(0)) 92 *valp = 0; 93 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) && 94 (env->context.valid_regs & 95 (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) ) 96 *valp = env->context.br[regid - UWX_REG_BR(1)]; 97 else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(5) && 98 (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) { 99 valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0; 100 valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1; 101 } 102 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_BR(31) && 103 (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) { 104 valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0; 105 valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1; 106 } 107 else if ( (regid < NSPECIALREG) || 108 (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 109 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) { 110 if (env->copyin == 0) 111 return UWX_ERR_NOCALLBACKS; 112 n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 113 regid, DWORDSZ, env->cb_token); 114 if (n != DWORDSZ) 115 status = UWX_ERR_COPYIN_REG; 116 } 117 else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(127)) { 118 if (env->copyin == 0) 119 return UWX_ERR_NOCALLBACKS; 120 n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 121 regid, 2*DWORDSZ, env->cb_token); 122 if (n != 2*DWORDSZ) 123 status = UWX_ERR_COPYIN_REG; 124 } 125 else if (regid == UWX_REG_FR(0)) { 126 valp[0] = 0; 127 valp[1] = 0; 128 } 129 else if (regid == UWX_REG_FR(1)) { 130 valp[0] = 0x000000000000ffffULL; 131 valp[1] = 0x8000000000000000ULL; 132 } 133 else 134 status = UWX_ERR_BADREGID; 135 return status; 136} 137 138int uwx_get_nat(struct uwx_env *env, int regid, int *natp) 139{ 140 int status; 141 int sor; 142 int rrb_gr; 143 uint64_t bsp; 144 uint64_t natcollp; 145 uint64_t natcoll; 146 int n; 147 148 if (env == 0) 149 return UWX_ERR_NOENV; 150 151 status = UWX_OK; 152 153 if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 154 (env->context.valid_regs & 155 (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) { 156 *natp = (env->context.special[UWX_REG_PRIUNAT] >> 157 (regid - UWX_REG_GR(4)) ) & 0x01; 158 } 159 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 160 if (env->copyin == 0) 161 return UWX_ERR_NOCALLBACKS; 162 bsp = env->context.special[UWX_REG_BSP]; 163 regid -= UWX_REG_GR(32); 164 sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 165 rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 166 if (sor != 0 && rrb_gr != 0 && regid < sor) { 167 regid = (regid + rrb_gr) % sor; 168 } 169 bsp = uwx_add_to_bsp(bsp, regid); 170 natcollp = bsp | 0x01f8; 171 if (natcollp >= bsp) 172 n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll, 173 (uint64_t)UWX_REG_RNAT, DWORDSZ, env->cb_token); 174 else 175 n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, 176 bsp, DWORDSZ, env->cb_token); 177 if (n != DWORDSZ) 178 return UWX_ERR_COPYIN_RSTK; 179 *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; 180 } 181 else if (regid == UWX_REG_GR(0)) 182 *natp = 0; 183 else 184 status = UWX_ERR_BADREGID; 185 return status; 186} 187 188int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) 189{ 190 int status; 191 int sor; 192 int rrb_gr; 193 uint64_t bsp; 194 195 if (env == 0) 196 return UWX_ERR_NOENV; 197 198 status = UWX_OK; 199 200 if (regid < NSPECIALREG) 201 *dispp = env->history.special[regid]; 202 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) 203 *dispp = env->history.gr[regid - UWX_REG_GR(4)]; 204 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 205 bsp = env->context.special[UWX_REG_BSP]; 206 regid -= UWX_REG_GR(32); 207 sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 208 rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 209 if (sor != 0 && rrb_gr != 0 && regid < sor) 210 regid = (regid + rrb_gr) % sor; 211 bsp = uwx_add_to_bsp(bsp, regid); 212 *dispp = UWX_DISP_RSTK(bsp); 213 } 214 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5)) 215 *dispp = env->history.br[regid - UWX_REG_BR(1)]; 216 else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 217 *dispp = env->history.fr[regid - UWX_REG_FR(2)]; 218 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 219 *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4]; 220 else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 221 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) || 222 (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) ) 223 *dispp = UWX_DISP_REG(regid); 224 else 225 status = UWX_ERR_BADREGID; 226 return status; 227} 228 229int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 230{ 231 int status; 232 233 if (env == 0) 234 return UWX_ERR_NOENV; 235 236 if (regid < NSPECIALREG) { 237 env->context.special[regid] = val; 238 env->context.valid_regs |= 1 << regid; 239 status = UWX_OK; 240 } 241 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) { 242 env->context.gr[regid - UWX_REG_GR(4)] = val; 243 env->context.valid_regs |= 244 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT); 245 status = UWX_OK; 246 } 247 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 248 status = UWX_ERR_BADREGID; 249 } 250 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) { 251 env->context.br[regid - UWX_REG_BR(1)] = val; 252 env->context.valid_regs |= 253 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT); 254 status = UWX_OK; 255 } 256 else 257 status = UWX_ERR_BADREGID; 258 return status; 259} 260 261int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) 262{ 263 264 if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 265 regid -= UWX_REG_FR(2); 266 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 267 regid -= UWX_REG_FR(16) - 4; 268 else 269 return UWX_ERR_BADREGID; 270 271 env->context.fr[regid].part0 = val[0]; 272 env->context.fr[regid].part1 = val[1]; 273 env->context.valid_frs |= 1 << regid; 274 env->nsbreg = NSBREG; 275 return UWX_OK; 276} 277 278uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) 279{ 280 int bias; 281 282 /* 283 * Here's a picture of the backing store as modeled in 284 * the computations below. "X" marks NaT collections at 285 * every 0x1f8 mod 0x200 address. 286 * 287 * To make the NaT adjustments easier, we bias the current bsp 288 * by enough slots to place it at the previous NaT collection. 289 * Then we need to add the bias to the number of slots, 290 * then add 1 for every 63 slots to account for NaT collections. 291 * Then we can remove the bias again and add the adjusted 292 * number of slots to the bsp. 293 * 294 * 0 1f8 3f8 295 * +---------------------------------------------------------------+ 296 * | X X| 297 * +---------------------------------------------------------------+ 298 * <-------- bias --------> 299 * <--- nslots ---> 300 * ^ 301 * | 302 * bsp 303 * <------- adjusted (nslots + bias) -------> 304 305 * When subtracting from bsp, we bias the bsp in the opposite 306 * direction so that it is at the next NaT collection. 307 * 308 * 0 1f8 3f8 309 * +---------------------------------------------------------------+ 310 * | X X| 311 * +---------------------------------------------------------------+ 312 * <------- bias -------> 313 * <--- nslots ---> 314 * ^ 315 * | 316 * bsp 317 * <------ adjusted (nslots + bias) ------> 318 */ 319 320 if (nslots > 0) { 321 bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; 322 nslots += (nslots + bias) / 63; 323 } 324 else if (nslots < 0) { 325 bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ; 326 nslots -= (-nslots + bias) / 63; 327 } 328 return bsp + nslots * DWORDSZ; 329} 330