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