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