uwx_context.c revision 120925
1115013Smarcel/* 2115013Smarcel * Copyright (c) 2002,2003 Hewlett-Packard Company 3115013Smarcel * 4115013Smarcel * Permission is hereby granted, free of charge, to any person obtaining a 5115013Smarcel * copy of this software and associated documentation files (the "Software"), 6115013Smarcel * to deal in the Software without restriction, including without limitation 7115013Smarcel * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8115013Smarcel * and/or sell copies of the Software, and to permit persons to whom the 9115013Smarcel * Software is furnished to do so, subject to the following conditions: 10115013Smarcel * 11115013Smarcel * The above copyright notice and this permission notice shall be included 12115013Smarcel * in all copies or substantial portions of the Software. 13115013Smarcel * 14115013Smarcel * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15115013Smarcel * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16115013Smarcel * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17115013Smarcel * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18115013Smarcel * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19115013Smarcel * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20115013Smarcel * DEALINGS IN THE SOFTWARE. 21115013Smarcel */ 22115013Smarcel 23115013Smarcel#include "uwx_env.h" 24115013Smarcel#include "uwx_context.h" 25115013Smarcel#include "uwx_scoreboard.h" 26120925Smarcel#include "uwx_step.h" 27115013Smarcel#include "uwx_trace.h" 28115013Smarcel 29115013Smarcelint uwx_init_context( 30115013Smarcel struct uwx_env *env, 31115013Smarcel uint64_t ip, 32115013Smarcel uint64_t sp, 33115013Smarcel uint64_t bsp, 34115013Smarcel uint64_t cfm) 35115013Smarcel{ 36115013Smarcel int i; 37115013Smarcel 38115013Smarcel if (env == 0) 39115013Smarcel return UWX_ERR_NOENV; 40115013Smarcel 41115013Smarcel env->context.special[UWX_REG_IP] = ip; 42115013Smarcel env->context.special[UWX_REG_SP] = sp; 43115013Smarcel env->context.special[UWX_REG_BSP] = bsp; 44115013Smarcel env->context.special[UWX_REG_CFM] = cfm; 45115013Smarcel for (i = UWX_REG_RP; i < NSPECIALREG; i++) 46115013Smarcel env->context.special[i] = 0; 47115013Smarcel for (i = 0; i < NPRESERVEDGR; i++) 48115013Smarcel env->context.gr[i] = 0; 49115013Smarcel env->context.valid_regs = VALID_BASIC4; 50120925Smarcel env->context.valid_frs = 0; 51115013Smarcel env->rstate = 0; 52115013Smarcel (void)uwx_init_history(env); 53115013Smarcel return UWX_OK; 54115013Smarcel} 55115013Smarcel 56115013Smarcelint uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp) 57115013Smarcel{ 58115013Smarcel int status; 59115013Smarcel int sor; 60115013Smarcel int rrb_gr; 61115013Smarcel uint64_t bsp; 62115013Smarcel int n; 63115013Smarcel 64115013Smarcel if (env == 0) 65115013Smarcel return UWX_ERR_NOENV; 66115013Smarcel 67115013Smarcel status = UWX_OK; 68115013Smarcel 69120925Smarcel if (regid == UWX_REG_GR(12)) 70120925Smarcel regid = UWX_REG_SP; 71115013Smarcel if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid))) 72115013Smarcel *valp = env->context.special[regid]; 73120925Smarcel else if (regid == UWX_REG_PSP || regid == UWX_REG_RP || 74120925Smarcel regid == UWX_REG_PFS) { 75120925Smarcel status = uwx_restore_markers(env); 76120925Smarcel if (status != UWX_OK) 77120925Smarcel return status; 78120925Smarcel *valp = env->context.special[regid]; 79120925Smarcel } 80115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 81115013Smarcel (env->context.valid_regs & 82115013Smarcel (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) 83115013Smarcel *valp = env->context.gr[regid - UWX_REG_GR(4)]; 84115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 85115013Smarcel if (env->copyin == 0) 86115013Smarcel return UWX_ERR_NOCALLBACKS; 87115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 88115013Smarcel TRACE_C_GET_REG(regid, bsp) 89115013Smarcel regid -= UWX_REG_GR(32); 90115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 91115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 92115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) { 93115013Smarcel TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor) 94115013Smarcel regid = (regid + rrb_gr) % sor; 95115013Smarcel } 96115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 97115013Smarcel n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp, 98115013Smarcel bsp, DWORDSZ, env->cb_token); 99115013Smarcel if (n != DWORDSZ) 100115013Smarcel status = UWX_ERR_COPYIN_RSTK; 101115013Smarcel } 102115013Smarcel else if (regid == UWX_REG_GR(0)) 103115013Smarcel *valp = 0; 104115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) && 105115013Smarcel (env->context.valid_regs & 106115013Smarcel (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) ) 107115013Smarcel *valp = env->context.br[regid - UWX_REG_BR(1)]; 108120925Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) && 109120925Smarcel (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) { 110115013Smarcel valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0; 111115013Smarcel valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1; 112115013Smarcel } 113120925Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) && 114120925Smarcel (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) { 115115013Smarcel valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0; 116115013Smarcel valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1; 117115013Smarcel } 118115013Smarcel else if ( (regid < NSPECIALREG) || 119115013Smarcel (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 120115013Smarcel (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) { 121115013Smarcel if (env->copyin == 0) 122115013Smarcel return UWX_ERR_NOCALLBACKS; 123115013Smarcel n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 124115013Smarcel regid, DWORDSZ, env->cb_token); 125115013Smarcel if (n != DWORDSZ) 126115013Smarcel status = UWX_ERR_COPYIN_REG; 127115013Smarcel } 128120925Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) { 129115013Smarcel if (env->copyin == 0) 130115013Smarcel return UWX_ERR_NOCALLBACKS; 131115013Smarcel n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp, 132115013Smarcel regid, 2*DWORDSZ, env->cb_token); 133115013Smarcel if (n != 2*DWORDSZ) 134115013Smarcel status = UWX_ERR_COPYIN_REG; 135115013Smarcel } 136115013Smarcel else if (regid == UWX_REG_FR(0)) { 137115013Smarcel valp[0] = 0; 138115013Smarcel valp[1] = 0; 139115013Smarcel } 140115013Smarcel else if (regid == UWX_REG_FR(1)) { 141115013Smarcel valp[0] = 0x000000000000ffffULL; 142115013Smarcel valp[1] = 0x8000000000000000ULL; 143115013Smarcel } 144115013Smarcel else 145115013Smarcel status = UWX_ERR_BADREGID; 146115013Smarcel return status; 147115013Smarcel} 148115013Smarcel 149115013Smarcelint uwx_get_nat(struct uwx_env *env, int regid, int *natp) 150115013Smarcel{ 151115013Smarcel int status; 152115013Smarcel int sor; 153115013Smarcel int rrb_gr; 154115013Smarcel uint64_t bsp; 155115013Smarcel uint64_t natcollp; 156115013Smarcel uint64_t natcoll; 157115013Smarcel int n; 158115013Smarcel 159115013Smarcel if (env == 0) 160115013Smarcel return UWX_ERR_NOENV; 161115013Smarcel 162115013Smarcel status = UWX_OK; 163115013Smarcel 164115013Smarcel if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) && 165115013Smarcel (env->context.valid_regs & 166115013Smarcel (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) { 167115013Smarcel *natp = (env->context.special[UWX_REG_PRIUNAT] >> 168115013Smarcel (regid - UWX_REG_GR(4)) ) & 0x01; 169115013Smarcel } 170115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 171115013Smarcel if (env->copyin == 0) 172115013Smarcel return UWX_ERR_NOCALLBACKS; 173115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 174115013Smarcel regid -= UWX_REG_GR(32); 175115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 176115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 177115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) { 178115013Smarcel regid = (regid + rrb_gr) % sor; 179115013Smarcel } 180115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 181115013Smarcel natcollp = bsp | 0x01f8; 182115013Smarcel if (natcollp >= bsp) 183115013Smarcel n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll, 184120925Smarcel (uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token); 185115013Smarcel else 186115013Smarcel n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, 187115013Smarcel bsp, DWORDSZ, env->cb_token); 188115013Smarcel if (n != DWORDSZ) 189115013Smarcel return UWX_ERR_COPYIN_RSTK; 190115013Smarcel *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; 191115013Smarcel } 192115013Smarcel else if (regid == UWX_REG_GR(0)) 193115013Smarcel *natp = 0; 194115013Smarcel else 195115013Smarcel status = UWX_ERR_BADREGID; 196115013Smarcel return status; 197115013Smarcel} 198115013Smarcel 199115013Smarcelint uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) 200115013Smarcel{ 201115013Smarcel int status; 202115013Smarcel int sor; 203115013Smarcel int rrb_gr; 204115013Smarcel uint64_t bsp; 205115013Smarcel 206115013Smarcel if (env == 0) 207115013Smarcel return UWX_ERR_NOENV; 208115013Smarcel 209115013Smarcel status = UWX_OK; 210115013Smarcel 211120925Smarcel if (regid == UWX_REG_GR(12)) 212120925Smarcel regid = UWX_REG_SP; 213115013Smarcel if (regid < NSPECIALREG) 214115013Smarcel *dispp = env->history.special[regid]; 215115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) 216115013Smarcel *dispp = env->history.gr[regid - UWX_REG_GR(4)]; 217115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 218115013Smarcel bsp = env->context.special[UWX_REG_BSP]; 219115013Smarcel regid -= UWX_REG_GR(32); 220115013Smarcel sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 221115013Smarcel rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 222115013Smarcel if (sor != 0 && rrb_gr != 0 && regid < sor) 223115013Smarcel regid = (regid + rrb_gr) % sor; 224115013Smarcel bsp = uwx_add_to_bsp(bsp, regid); 225115013Smarcel *dispp = UWX_DISP_RSTK(bsp); 226115013Smarcel } 227115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5)) 228115013Smarcel *dispp = env->history.br[regid - UWX_REG_BR(1)]; 229115013Smarcel else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 230115013Smarcel *dispp = env->history.fr[regid - UWX_REG_FR(2)]; 231115013Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 232115013Smarcel *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4]; 233115013Smarcel else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 234115013Smarcel (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) || 235115013Smarcel (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) ) 236115013Smarcel *dispp = UWX_DISP_REG(regid); 237115013Smarcel else 238115013Smarcel status = UWX_ERR_BADREGID; 239115013Smarcel return status; 240115013Smarcel} 241115013Smarcel 242115013Smarcelint uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 243115013Smarcel{ 244115013Smarcel int status; 245115013Smarcel 246115013Smarcel if (env == 0) 247115013Smarcel return UWX_ERR_NOENV; 248115013Smarcel 249120925Smarcel if (regid == UWX_REG_GR(12)) 250120925Smarcel regid = UWX_REG_SP; 251115013Smarcel if (regid < NSPECIALREG) { 252115013Smarcel env->context.special[regid] = val; 253115013Smarcel env->context.valid_regs |= 1 << regid; 254115013Smarcel status = UWX_OK; 255115013Smarcel } 256115013Smarcel else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) { 257115013Smarcel env->context.gr[regid - UWX_REG_GR(4)] = val; 258115013Smarcel env->context.valid_regs |= 259115013Smarcel 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT); 260115013Smarcel status = UWX_OK; 261115013Smarcel } 262115013Smarcel else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 263115013Smarcel status = UWX_ERR_BADREGID; 264115013Smarcel } 265115013Smarcel else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) { 266115013Smarcel env->context.br[regid - UWX_REG_BR(1)] = val; 267115013Smarcel env->context.valid_regs |= 268115013Smarcel 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT); 269115013Smarcel status = UWX_OK; 270115013Smarcel } 271115013Smarcel else 272115013Smarcel status = UWX_ERR_BADREGID; 273115013Smarcel return status; 274115013Smarcel} 275115013Smarcel 276115013Smarcelint uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) 277115013Smarcel{ 278115013Smarcel 279115013Smarcel if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 280115013Smarcel regid -= UWX_REG_FR(2); 281115013Smarcel else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 282115013Smarcel regid -= UWX_REG_FR(16) - 4; 283115013Smarcel else 284115013Smarcel return UWX_ERR_BADREGID; 285115013Smarcel 286115013Smarcel env->context.fr[regid].part0 = val[0]; 287115013Smarcel env->context.fr[regid].part1 = val[1]; 288115013Smarcel env->context.valid_frs |= 1 << regid; 289115013Smarcel env->nsbreg = NSBREG; 290115013Smarcel return UWX_OK; 291115013Smarcel} 292115013Smarcel 293115013Smarceluint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) 294115013Smarcel{ 295115013Smarcel int bias; 296115013Smarcel 297115013Smarcel /* 298115013Smarcel * Here's a picture of the backing store as modeled in 299115013Smarcel * the computations below. "X" marks NaT collections at 300115013Smarcel * every 0x1f8 mod 0x200 address. 301115013Smarcel * 302115013Smarcel * To make the NaT adjustments easier, we bias the current bsp 303115013Smarcel * by enough slots to place it at the previous NaT collection. 304115013Smarcel * Then we need to add the bias to the number of slots, 305115013Smarcel * then add 1 for every 63 slots to account for NaT collections. 306115013Smarcel * Then we can remove the bias again and add the adjusted 307115013Smarcel * number of slots to the bsp. 308115013Smarcel * 309115013Smarcel * 0 1f8 3f8 310115013Smarcel * +---------------------------------------------------------------+ 311115013Smarcel * | X X| 312115013Smarcel * +---------------------------------------------------------------+ 313115013Smarcel * <-------- bias --------> 314115013Smarcel * <--- nslots ---> 315115013Smarcel * ^ 316115013Smarcel * | 317115013Smarcel * bsp 318115013Smarcel * <------- adjusted (nslots + bias) -------> 319115013Smarcel 320115013Smarcel * When subtracting from bsp, we bias the bsp in the opposite 321115013Smarcel * direction so that it is at the next NaT collection. 322115013Smarcel * 323115013Smarcel * 0 1f8 3f8 324115013Smarcel * +---------------------------------------------------------------+ 325115013Smarcel * | X X| 326115013Smarcel * +---------------------------------------------------------------+ 327115013Smarcel * <------- bias -------> 328115013Smarcel * <--- nslots ---> 329115013Smarcel * ^ 330115013Smarcel * | 331115013Smarcel * bsp 332115013Smarcel * <------ adjusted (nslots + bias) ------> 333115013Smarcel */ 334115013Smarcel 335115013Smarcel if (nslots > 0) { 336115013Smarcel bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; 337115013Smarcel nslots += (nslots + bias) / 63; 338115013Smarcel } 339115013Smarcel else if (nslots < 0) { 340115013Smarcel bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ; 341115013Smarcel nslots -= (-nslots + bias) / 63; 342115013Smarcel } 343115013Smarcel return bsp + nslots * DWORDSZ; 344115013Smarcel} 345