1115013Smarcel/* 2160157SmarcelCopyright (c) 2003-2006 Hewlett-Packard Development Company, L.P. 3121642SmarcelPermission is hereby granted, free of charge, to any person 4121642Smarcelobtaining a copy of this software and associated documentation 5121642Smarcelfiles (the "Software"), to deal in the Software without 6121642Smarcelrestriction, including without limitation the rights to use, 7121642Smarcelcopy, modify, merge, publish, distribute, sublicense, and/or sell 8121642Smarcelcopies of the Software, and to permit persons to whom the 9121642SmarcelSoftware is furnished to do so, subject to the following 10121642Smarcelconditions: 11115013Smarcel 12121642SmarcelThe above copyright notice and this permission notice shall be 13121642Smarcelincluded in all copies or substantial portions of the Software. 14121642Smarcel 15121642SmarcelTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16121642SmarcelEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17121642SmarcelOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18121642SmarcelNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19121642SmarcelHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20121642SmarcelWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21121642SmarcelFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22121642SmarcelOTHER DEALINGS IN THE SOFTWARE. 23121642Smarcel*/ 24121642Smarcel 25115013Smarcel#include "uwx_env.h" 26115013Smarcel#include "uwx_scoreboard.h" 27120925Smarcel#include "uwx_step.h" 28115013Smarcel#include "uwx_trace.h" 29115013Smarcel 30115013Smarcelint uwx_init_context( 31115013Smarcel struct uwx_env *env, 32115013Smarcel uint64_t ip, 33115013Smarcel uint64_t sp, 34115013Smarcel uint64_t bsp, 35115013Smarcel uint64_t cfm) 36115013Smarcel{ 37115013Smarcel int i; 38115013Smarcel 39115013Smarcel if (env == 0) 40115013Smarcel return UWX_ERR_NOENV; 41115013Smarcel 42115013Smarcel env->context.special[UWX_REG_IP] = ip; 43115013Smarcel env->context.special[UWX_REG_SP] = sp; 44115013Smarcel env->context.special[UWX_REG_BSP] = bsp; 45115013Smarcel env->context.special[UWX_REG_CFM] = cfm; 46115013Smarcel for (i = UWX_REG_RP; i < NSPECIALREG; i++) 47115013Smarcel env->context.special[i] = 0; 48115013Smarcel for (i = 0; i < NPRESERVEDGR; i++) 49115013Smarcel env->context.gr[i] = 0; 50115013Smarcel env->context.valid_regs = VALID_BASIC4; 51120925Smarcel env->context.valid_frs = 0; 52115013Smarcel env->rstate = 0; 53115013Smarcel (void)uwx_init_history(env); 54115013Smarcel return UWX_OK; 55115013Smarcel} 56115013Smarcel 57115013Smarcelint uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp) 58115013Smarcel{ 59115013Smarcel int status; 60115013Smarcel int sor; 61115013Smarcel int rrb_gr; 62115013Smarcel uint64_t bsp; 63115013Smarcel int n; 64115013Smarcel 65115013Smarcel if (env == 0) 66115013Smarcel return UWX_ERR_NOENV; 67115013Smarcel 68115013Smarcel status = UWX_OK; 69115013Smarcel 70120925Smarcel if (regid == UWX_REG_GR(12)) 71120925Smarcel regid = UWX_REG_SP; 72115013Smarcel if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid))) 73115013Smarcel *valp = env->context.special[regid]; 74120925Smarcel else if (regid == UWX_REG_PSP || regid == UWX_REG_RP || 75120925Smarcel regid == UWX_REG_PFS) { 76120925Smarcel status = uwx_restore_markers(env); 77120925Smarcel if (status != UWX_OK) 78120925Smarcel return status; 79120925Smarcel *valp = env->context.special[regid]; 80120925Smarcel } 81115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 82115013Smarcel (env->context.valid_regs & 83115013Smarcel (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) 84115013Smarcel *valp = env->context.gr[regid - UWX_REG_GR(4)]; 85115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 86115013Smarcel if (env->copyin == 0) 87115013Smarcel return UWX_ERR_NOCALLBACKS; 88115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 89115013Smarcel TRACE_C_GET_REG(regid, bsp) 90115013Smarcel regid -= UWX_REG_GR(32); 91115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 92115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 93115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) { 94115013Smarcel TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor) 95115013Smarcel regid = (regid + rrb_gr) % sor; 96115013Smarcel } 97115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 98115013Smarcel n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp, 99115013Smarcel bsp, DWORDSZ, env->cb_token); 100115013Smarcel if (n != DWORDSZ) 101115013Smarcel status = UWX_ERR_COPYIN_RSTK; 102115013Smarcel } 103115013Smarcel else if (regid == UWX_REG_GR(0)) 104115013Smarcel *valp = 0; 105115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) && 106115013Smarcel (env->context.valid_regs & 107115013Smarcel (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) ) 108115013Smarcel *valp = env->context.br[regid - UWX_REG_BR(1)]; 109120925Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) && 110120925Smarcel (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) { 111115013Smarcel valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0; 112115013Smarcel valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1; 113115013Smarcel } 114120925Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) && 115120925Smarcel (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) { 116115013Smarcel valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0; 117115013Smarcel valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1; 118115013Smarcel } 119115013Smarcel else if ( (regid < NSPECIALREG) || 120115013Smarcel (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 121115013Smarcel (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) { 122115013Smarcel if (env->copyin == 0) 123115013Smarcel return UWX_ERR_NOCALLBACKS; 124115013Smarcel n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 125115013Smarcel regid, DWORDSZ, env->cb_token); 126115013Smarcel if (n != DWORDSZ) 127115013Smarcel status = UWX_ERR_COPYIN_REG; 128115013Smarcel } 129120925Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) { 130115013Smarcel if (env->copyin == 0) 131115013Smarcel return UWX_ERR_NOCALLBACKS; 132115013Smarcel n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 133115013Smarcel regid, 2*DWORDSZ, env->cb_token); 134115013Smarcel if (n != 2*DWORDSZ) 135115013Smarcel status = UWX_ERR_COPYIN_REG; 136115013Smarcel } 137115013Smarcel else if (regid == UWX_REG_FR(0)) { 138115013Smarcel valp[0] = 0; 139115013Smarcel valp[1] = 0; 140115013Smarcel } 141115013Smarcel else if (regid == UWX_REG_FR(1)) { 142115013Smarcel valp[0] = 0x000000000000ffffULL; 143115013Smarcel valp[1] = 0x8000000000000000ULL; 144115013Smarcel } 145115013Smarcel else 146115013Smarcel status = UWX_ERR_BADREGID; 147115013Smarcel return status; 148115013Smarcel} 149115013Smarcel 150115013Smarcelint uwx_get_nat(struct uwx_env *env, int regid, int *natp) 151115013Smarcel{ 152115013Smarcel int status; 153115013Smarcel int sor; 154115013Smarcel int rrb_gr; 155115013Smarcel uint64_t bsp; 156115013Smarcel uint64_t natcollp; 157115013Smarcel uint64_t natcoll; 158115013Smarcel int n; 159115013Smarcel 160115013Smarcel if (env == 0) 161115013Smarcel return UWX_ERR_NOENV; 162115013Smarcel 163115013Smarcel status = UWX_OK; 164115013Smarcel 165115013Smarcel if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 166115013Smarcel (env->context.valid_regs & 167115013Smarcel (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) { 168115013Smarcel *natp = (env->context.special[UWX_REG_PRIUNAT] >> 169115013Smarcel (regid - UWX_REG_GR(4)) ) & 0x01; 170115013Smarcel } 171115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 172115013Smarcel if (env->copyin == 0) 173115013Smarcel return UWX_ERR_NOCALLBACKS; 174115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 175115013Smarcel regid -= UWX_REG_GR(32); 176115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 177115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 178115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) { 179115013Smarcel regid = (regid + rrb_gr) % sor; 180115013Smarcel } 181115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 182115013Smarcel natcollp = bsp | 0x01f8; 183129059Smarcel n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, 184160157Smarcel natcollp, DWORDSZ, env->cb_token); 185115013Smarcel if (n != DWORDSZ) 186115013Smarcel return UWX_ERR_COPYIN_RSTK; 187115013Smarcel *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; 188115013Smarcel } 189115013Smarcel else if (regid == UWX_REG_GR(0)) 190115013Smarcel *natp = 0; 191115013Smarcel else 192115013Smarcel status = UWX_ERR_BADREGID; 193115013Smarcel return status; 194115013Smarcel} 195115013Smarcel 196115013Smarcelint uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) 197115013Smarcel{ 198115013Smarcel int status; 199115013Smarcel int sor; 200115013Smarcel int rrb_gr; 201115013Smarcel uint64_t bsp; 202115013Smarcel 203115013Smarcel if (env == 0) 204115013Smarcel return UWX_ERR_NOENV; 205115013Smarcel 206115013Smarcel status = UWX_OK; 207115013Smarcel 208120925Smarcel if (regid == UWX_REG_GR(12)) 209120925Smarcel regid = UWX_REG_SP; 210160157Smarcel if (regid < NSPECIALREG) { 211160157Smarcel if (regid == UWX_REG_PSP || regid == UWX_REG_RP || 212160157Smarcel regid == UWX_REG_PFS) { 213160157Smarcel if (!(env->context.valid_regs & (1 << regid))) { 214160157Smarcel status = uwx_restore_markers(env); 215160157Smarcel if (status != UWX_OK) 216160157Smarcel return status; 217160157Smarcel } 218160157Smarcel } 219115013Smarcel *dispp = env->history.special[regid]; 220160157Smarcel } 221115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) 222115013Smarcel *dispp = env->history.gr[regid - UWX_REG_GR(4)]; 223115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 224115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 225115013Smarcel regid -= UWX_REG_GR(32); 226115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 227115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 228115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) 229115013Smarcel regid = (regid + rrb_gr) % sor; 230115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 231115013Smarcel *dispp = UWX_DISP_RSTK(bsp); 232115013Smarcel } 233115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5)) 234115013Smarcel *dispp = env->history.br[regid - UWX_REG_BR(1)]; 235115013Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 236115013Smarcel *dispp = env->history.fr[regid - UWX_REG_FR(2)]; 237115013Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 238115013Smarcel *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4]; 239115013Smarcel else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 240115013Smarcel (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) || 241115013Smarcel (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) ) 242115013Smarcel *dispp = UWX_DISP_REG(regid); 243115013Smarcel else 244115013Smarcel status = UWX_ERR_BADREGID; 245115013Smarcel return status; 246115013Smarcel} 247115013Smarcel 248115013Smarcelint uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 249115013Smarcel{ 250115013Smarcel int status; 251115013Smarcel 252115013Smarcel if (env == 0) 253115013Smarcel return UWX_ERR_NOENV; 254115013Smarcel 255120925Smarcel if (regid == UWX_REG_GR(12)) 256120925Smarcel regid = UWX_REG_SP; 257115013Smarcel if (regid < NSPECIALREG) { 258115013Smarcel env->context.special[regid] = val; 259115013Smarcel env->context.valid_regs |= 1 << regid; 260115013Smarcel status = UWX_OK; 261115013Smarcel } 262115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) { 263115013Smarcel env->context.gr[regid - UWX_REG_GR(4)] = val; 264115013Smarcel env->context.valid_regs |= 265115013Smarcel 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT); 266115013Smarcel status = UWX_OK; 267115013Smarcel } 268115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 269115013Smarcel status = UWX_ERR_BADREGID; 270115013Smarcel } 271115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) { 272115013Smarcel env->context.br[regid - UWX_REG_BR(1)] = val; 273115013Smarcel env->context.valid_regs |= 274115013Smarcel 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT); 275115013Smarcel status = UWX_OK; 276115013Smarcel } 277115013Smarcel else 278115013Smarcel status = UWX_ERR_BADREGID; 279115013Smarcel return status; 280115013Smarcel} 281115013Smarcel 282115013Smarcelint uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) 283115013Smarcel{ 284115013Smarcel 285115013Smarcel if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 286115013Smarcel regid -= UWX_REG_FR(2); 287115013Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 288115013Smarcel regid -= UWX_REG_FR(16) - 4; 289115013Smarcel else 290115013Smarcel return UWX_ERR_BADREGID; 291115013Smarcel 292115013Smarcel env->context.fr[regid].part0 = val[0]; 293115013Smarcel env->context.fr[regid].part1 = val[1]; 294115013Smarcel env->context.valid_frs |= 1 << regid; 295115013Smarcel env->nsbreg = NSBREG; 296115013Smarcel return UWX_OK; 297115013Smarcel} 298115013Smarcel 299115013Smarceluint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) 300115013Smarcel{ 301115013Smarcel int bias; 302115013Smarcel 303115013Smarcel /* 304115013Smarcel * Here's a picture of the backing store as modeled in 305115013Smarcel * the computations below. "X" marks NaT collections at 306115013Smarcel * every 0x1f8 mod 0x200 address. 307115013Smarcel * 308115013Smarcel * To make the NaT adjustments easier, we bias the current bsp 309115013Smarcel * by enough slots to place it at the previous NaT collection. 310115013Smarcel * Then we need to add the bias to the number of slots, 311115013Smarcel * then add 1 for every 63 slots to account for NaT collections. 312115013Smarcel * Then we can remove the bias again and add the adjusted 313115013Smarcel * number of slots to the bsp. 314115013Smarcel * 315115013Smarcel * 0 1f8 3f8 316115013Smarcel * +---------------------------------------------------------------+ 317115013Smarcel * | X X| 318115013Smarcel * +---------------------------------------------------------------+ 319115013Smarcel * <-------- bias --------> 320115013Smarcel * <--- nslots ---> 321115013Smarcel * ^ 322115013Smarcel * | 323115013Smarcel * bsp 324160157Smarcel * <------------ nslots + bias -----------> 325115013Smarcel 326129059Smarcel * When subtracting from bsp, we avoid depending on the sign of 327129059Smarcel * the quotient by adding 63*8 before division and subtracting 8 328129059Smarcel * after division. (Assumes that we will never be called upon 329129059Smarcel * to subtract more than 504 slots from bsp.) 330115013Smarcel * 331115013Smarcel * 0 1f8 3f8 332115013Smarcel * +---------------------------------------------------------------+ 333115013Smarcel * | X X| 334115013Smarcel * +---------------------------------------------------------------+ 335129059Smarcel * <-- bias --> 336160157Smarcel * <--- (-nslots) ---> 337129059Smarcel * ^ 338129059Smarcel * | 339129059Smarcel * bsp 340129059Smarcel * <-----------------> 341160157Smarcel * -(nslots + bias) 342115013Smarcel */ 343115013Smarcel 344129059Smarcel bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; 345129059Smarcel nslots += (nslots + bias + 63*8) / 63 - 8; 346129059Smarcel return bsp + nslots * DWORDSZ; 347129059Smarcel} 348129059Smarcel 349160163Smarcel#if 0 350129059Smarcelint uwx_selftest_bsp_arithmetic() 351129059Smarcel{ 352129059Smarcel int i; 353129059Smarcel int j; 354129059Smarcel int r; 355129059Smarcel uint64_t bstore[161]; 356129059Smarcel uint64_t *bsp; 357129059Smarcel uint64_t *p; 358129059Smarcel int failed = 0; 359129059Smarcel 360129059Smarcel printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore); 361129059Smarcel r = 0; 362129059Smarcel bsp = bstore; 363129059Smarcel for (i = 0; i < 161; i++) { 364129059Smarcel if (((unsigned int)bsp & 0x1f8) == 0x1f8) 365129059Smarcel *bsp++ = 1000 + r; 366129059Smarcel else 367129059Smarcel *bsp++ = r++; 368115013Smarcel } 369129059Smarcel 370129059Smarcel printf("uwx_selftest_bsp_arithmetic: plus tests...\n"); 371129059Smarcel bsp = bstore; 372129059Smarcel for (i = 0; i < 64; i++) { 373129059Smarcel r = (int)*bsp; 374129059Smarcel if (r >= 1000) 375129059Smarcel r -= 1000; 376129059Smarcel for (j = 0; j < 96; j++) { 377160157Smarcel p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j); 378129059Smarcel if (*p != (r + j)) { 379129059Smarcel failed++; 380129059Smarcel printf("%d [%08lx] + %d -> %08lx ", 381129059Smarcel i, (unsigned int)bsp, j, (unsigned int)p); 382129059Smarcel printf("(read %d instead of %d)\n", (int)*p, r + j); 383129059Smarcel } 384129059Smarcel } 385129059Smarcel bsp++; 386115013Smarcel } 387129059Smarcel 388129059Smarcel printf("uwx_selftest_bsp_arithmetic: minus tests...\n"); 389129059Smarcel bsp = &bstore[161]; 390129059Smarcel for (i = 63; i >= 0; i--) { 391129059Smarcel bsp--; 392129059Smarcel r = (int)*bsp; 393129059Smarcel if (r >= 1000) 394129059Smarcel r -= 1000; 395129059Smarcel for (j = 0; j < 96; j++) { 396160157Smarcel p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j); 397129059Smarcel if (*p != (r - j)) { 398129059Smarcel failed++; 399129059Smarcel printf("%d [%08lx] - %d -> %08lx ", 400129059Smarcel i, (unsigned int)bsp, j, (unsigned int)p); 401129059Smarcel printf("(read %d instead of %d)\n", (int)*p, r - j); 402129059Smarcel } 403129059Smarcel } 404129059Smarcel } 405129059Smarcel 406129059Smarcel return failed; 407115013Smarcel} 408160163Smarcel#endif 409