uwx_context.c revision 120925
1142425Snectar/* 255714Skris * Copyright (c) 2002,2003 Hewlett-Packard Company 355714Skris * 455714Skris * Permission is hereby granted, free of charge, to any person obtaining a 555714Skris * copy of this software and associated documentation files (the "Software"), 655714Skris * to deal in the Software without restriction, including without limitation 755714Skris * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8109998Smarkm * and/or sell copies of the Software, and to permit persons to whom the 955714Skris * Software is furnished to do so, subject to the following conditions: 1055714Skris * 1155714Skris * The above copyright notice and this permission notice shall be included 1255714Skris * in all copies or substantial portions of the Software. 1355714Skris * 1455714Skris * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1555714Skris * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1655714Skris * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1755714Skris * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1855714Skris * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1955714Skris * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2055714Skris * DEALINGS IN THE SOFTWARE. 2155714Skris */ 2255714Skris 2355714Skris#include "uwx_env.h" 2455714Skris#include "uwx_context.h" 2555714Skris#include "uwx_scoreboard.h" 2655714Skris#include "uwx_step.h" 2755714Skris#include "uwx_trace.h" 2855714Skris 2955714Skrisint uwx_init_context( 3055714Skris struct uwx_env *env, 3155714Skris uint64_t ip, 3255714Skris uint64_t sp, 3355714Skris uint64_t bsp, 3455714Skris uint64_t cfm) 3555714Skris{ 3655714Skris int i; 3755714Skris 3855714Skris if (env == 0) 39160814Ssimon return UWX_ERR_NOENV; 40160814Ssimon 41160814Ssimon env->context.special[UWX_REG_IP] = ip; 42160814Ssimon env->context.special[UWX_REG_SP] = sp; 43160814Ssimon env->context.special[UWX_REG_BSP] = bsp; 44160814Ssimon env->context.special[UWX_REG_CFM] = cfm; 45160814Ssimon for (i = UWX_REG_RP; i < NSPECIALREG; i++) 46160814Ssimon env->context.special[i] = 0; 4768651Skris for (i = 0; i < NPRESERVEDGR; i++) 48160814Ssimon env->context.gr[i] = 0; 49160814Ssimon env->context.valid_regs = VALID_BASIC4; 50160814Ssimon env->context.valid_frs = 0; 51160814Ssimon env->rstate = 0; 52160814Ssimon (void)uwx_init_history(env); 53160814Ssimon return UWX_OK; 54160814Ssimon} 5555714Skris 5655714Skrisint uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp) 5755714Skris{ 58160814Ssimon int status; 5955714Skris int sor; 6055714Skris int rrb_gr; 6155714Skris uint64_t bsp; 6255714Skris int n; 6355714Skris 6455714Skris if (env == 0) 6555714Skris return UWX_ERR_NOENV; 6655714Skris 67109998Smarkm status = UWX_OK; 6855714Skris 6955714Skris if (regid == UWX_REG_GR(12)) 7055714Skris regid = UWX_REG_SP; 71160814Ssimon if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid))) 7255714Skris *valp = env->context.special[regid]; 73160814Ssimon else if (regid == UWX_REG_PSP || regid == UWX_REG_RP || 7455714Skris regid == UWX_REG_PFS) { 7555714Skris status = uwx_restore_markers(env); 76160814Ssimon if (status != UWX_OK) 7755714Skris return status; 78160814Ssimon *valp = env->context.special[regid]; 79109998Smarkm } 80109998Smarkm else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 81160814Ssimon (env->context.valid_regs & 82109998Smarkm (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) 83160814Ssimon *valp = env->context.gr[regid - UWX_REG_GR(4)]; 8455714Skris else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 8559191Skris if (env->copyin == 0) 8655714Skris return UWX_ERR_NOCALLBACKS; 8755714Skris bsp = env->context.special[UWX_REG_BSP]; 8855714Skris TRACE_C_GET_REG(regid, bsp) 8955714Skris regid -= UWX_REG_GR(32); 9055714Skris sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 9155714Skris rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 9255714Skris if (sor != 0 && rrb_gr != 0 && regid < sor) { 9355714Skris TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor) 9455714Skris regid = (regid + rrb_gr) % sor; 9555714Skris } 9655714Skris bsp = uwx_add_to_bsp(bsp, regid); 97160814Ssimon n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp, 98160814Ssimon bsp, DWORDSZ, env->cb_token); 99160814Ssimon if (n != DWORDSZ) 10055714Skris status = UWX_ERR_COPYIN_RSTK; 10155714Skris } 10255714Skris else if (regid == UWX_REG_GR(0)) 10355714Skris *valp = 0; 10455714Skris else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) && 10555714Skris (env->context.valid_regs & 10655714Skris (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) ) 10755714Skris *valp = env->context.br[regid - UWX_REG_BR(1)]; 10855714Skris else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) && 10955714Skris (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) { 11055714Skris valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0; 11155714Skris valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1; 11255714Skris } 11355714Skris else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) && 114160814Ssimon (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) { 115160814Ssimon valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0; 116160814Ssimon valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1; 117160814Ssimon } 118160814Ssimon else if ( (regid < NSPECIALREG) || 119160814Ssimon (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 120160814Ssimon (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) { 12155714Skris if (env->copyin == 0) 12255714Skris return UWX_ERR_NOCALLBACKS; 12355714Skris n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 12459191Skris regid, DWORDSZ, env->cb_token); 12559191Skris if (n != DWORDSZ) 12659191Skris status = UWX_ERR_COPYIN_REG; 127160814Ssimon } 12859191Skris else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) { 12959191Skris if (env->copyin == 0) 13059191Skris return UWX_ERR_NOCALLBACKS; 131160814Ssimon n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 13259191Skris regid, 2*DWORDSZ, env->cb_token); 13355714Skris if (n != 2*DWORDSZ) 13455714Skris status = UWX_ERR_COPYIN_REG; 13555714Skris } 13655714Skris else if (regid == UWX_REG_FR(0)) { 13755714Skris valp[0] = 0; 13855714Skris valp[1] = 0; 13955714Skris } 14055714Skris else if (regid == UWX_REG_FR(1)) { 14168651Skris valp[0] = 0x000000000000ffffULL; 14268651Skris valp[1] = 0x8000000000000000ULL; 14368651Skris } 14468651Skris else 14568651Skris status = UWX_ERR_BADREGID; 14655714Skris return status; 14755714Skris} 14855714Skris 14955714Skrisint uwx_get_nat(struct uwx_env *env, int regid, int *natp) 15055714Skris{ 15155714Skris int status; 15255714Skris int sor; 15355714Skris int rrb_gr; 15455714Skris uint64_t bsp; 15555714Skris uint64_t natcollp; 15655714Skris uint64_t natcoll; 15755714Skris int n; 15855714Skris 15955714Skris if (env == 0) 16055714Skris return UWX_ERR_NOENV; 16155714Skris 16255714Skris status = UWX_OK; 16355714Skris 16455714Skris if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 16555714Skris (env->context.valid_regs & 16655714Skris (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) { 167109998Smarkm *natp = (env->context.special[UWX_REG_PRIUNAT] >> 16855714Skris (regid - UWX_REG_GR(4)) ) & 0x01; 16955714Skris } 17055714Skris else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 17155714Skris if (env->copyin == 0) 17255714Skris return UWX_ERR_NOCALLBACKS; 17355714Skris bsp = env->context.special[UWX_REG_BSP]; 17455714Skris regid -= UWX_REG_GR(32); 17555714Skris sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 17655714Skris rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 17755714Skris if (sor != 0 && rrb_gr != 0 && regid < sor) { 17855714Skris regid = (regid + rrb_gr) % sor; 17955714Skris } 18055714Skris bsp = uwx_add_to_bsp(bsp, regid); 18155714Skris natcollp = bsp | 0x01f8; 18255714Skris if (natcollp >= bsp) 18355714Skris n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll, 18455714Skris (uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token); 18555714Skris else 18655714Skris n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, 18755714Skris bsp, DWORDSZ, env->cb_token); 18855714Skris if (n != DWORDSZ) 18955714Skris return UWX_ERR_COPYIN_RSTK; 190 *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; 191 } 192 else if (regid == UWX_REG_GR(0)) 193 *natp = 0; 194 else 195 status = UWX_ERR_BADREGID; 196 return status; 197} 198 199int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) 200{ 201 int status; 202 int sor; 203 int rrb_gr; 204 uint64_t bsp; 205 206 if (env == 0) 207 return UWX_ERR_NOENV; 208 209 status = UWX_OK; 210 211 if (regid == UWX_REG_GR(12)) 212 regid = UWX_REG_SP; 213 if (regid < NSPECIALREG) 214 *dispp = env->history.special[regid]; 215 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) 216 *dispp = env->history.gr[regid - UWX_REG_GR(4)]; 217 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 218 bsp = env->context.special[UWX_REG_BSP]; 219 regid -= UWX_REG_GR(32); 220 sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 221 rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 222 if (sor != 0 && rrb_gr != 0 && regid < sor) 223 regid = (regid + rrb_gr) % sor; 224 bsp = uwx_add_to_bsp(bsp, regid); 225 *dispp = UWX_DISP_RSTK(bsp); 226 } 227 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5)) 228 *dispp = env->history.br[regid - UWX_REG_BR(1)]; 229 else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 230 *dispp = env->history.fr[regid - UWX_REG_FR(2)]; 231 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 232 *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4]; 233 else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 234 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) || 235 (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) ) 236 *dispp = UWX_DISP_REG(regid); 237 else 238 status = UWX_ERR_BADREGID; 239 return status; 240} 241 242int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 243{ 244 int status; 245 246 if (env == 0) 247 return UWX_ERR_NOENV; 248 249 if (regid == UWX_REG_GR(12)) 250 regid = UWX_REG_SP; 251 if (regid < NSPECIALREG) { 252 env->context.special[regid] = val; 253 env->context.valid_regs |= 1 << regid; 254 status = UWX_OK; 255 } 256 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) { 257 env->context.gr[regid - UWX_REG_GR(4)] = val; 258 env->context.valid_regs |= 259 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT); 260 status = UWX_OK; 261 } 262 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 263 status = UWX_ERR_BADREGID; 264 } 265 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) { 266 env->context.br[regid - UWX_REG_BR(1)] = val; 267 env->context.valid_regs |= 268 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT); 269 status = UWX_OK; 270 } 271 else 272 status = UWX_ERR_BADREGID; 273 return status; 274} 275 276int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) 277{ 278 279 if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 280 regid -= UWX_REG_FR(2); 281 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 282 regid -= UWX_REG_FR(16) - 4; 283 else 284 return UWX_ERR_BADREGID; 285 286 env->context.fr[regid].part0 = val[0]; 287 env->context.fr[regid].part1 = val[1]; 288 env->context.valid_frs |= 1 << regid; 289 env->nsbreg = NSBREG; 290 return UWX_OK; 291} 292 293uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) 294{ 295 int bias; 296 297 /* 298 * Here's a picture of the backing store as modeled in 299 * the computations below. "X" marks NaT collections at 300 * every 0x1f8 mod 0x200 address. 301 * 302 * To make the NaT adjustments easier, we bias the current bsp 303 * by enough slots to place it at the previous NaT collection. 304 * Then we need to add the bias to the number of slots, 305 * then add 1 for every 63 slots to account for NaT collections. 306 * Then we can remove the bias again and add the adjusted 307 * number of slots to the bsp. 308 * 309 * 0 1f8 3f8 310 * +---------------------------------------------------------------+ 311 * | X X| 312 * +---------------------------------------------------------------+ 313 * <-------- bias --------> 314 * <--- nslots ---> 315 * ^ 316 * | 317 * bsp 318 * <------- adjusted (nslots + bias) -------> 319 320 * When subtracting from bsp, we bias the bsp in the opposite 321 * direction so that it is at the next NaT collection. 322 * 323 * 0 1f8 3f8 324 * +---------------------------------------------------------------+ 325 * | X X| 326 * +---------------------------------------------------------------+ 327 * <------- bias -------> 328 * <--- nslots ---> 329 * ^ 330 * | 331 * bsp 332 * <------ adjusted (nslots + bias) ------> 333 */ 334 335 if (nslots > 0) { 336 bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; 337 nslots += (nslots + bias) / 63; 338 } 339 else if (nslots < 0) { 340 bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ; 341 nslots -= (-nslots + bias) / 63; 342 } 343 return bsp + nslots * DWORDSZ; 344} 345