uwx_context.c revision 121642
1/* 2Copyright (c) 2003 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 if (natcollp >= bsp) 185 n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll, 186 (uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token); 187 else 188 n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll, 189 bsp, DWORDSZ, env->cb_token); 190 if (n != DWORDSZ) 191 return UWX_ERR_COPYIN_RSTK; 192 *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01; 193 } 194 else if (regid == UWX_REG_GR(0)) 195 *natp = 0; 196 else 197 status = UWX_ERR_BADREGID; 198 return status; 199} 200 201int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp) 202{ 203 int status; 204 int sor; 205 int rrb_gr; 206 uint64_t bsp; 207 208 if (env == 0) 209 return UWX_ERR_NOENV; 210 211 status = UWX_OK; 212 213 if (regid == UWX_REG_GR(12)) 214 regid = UWX_REG_SP; 215 if (regid < NSPECIALREG) 216 *dispp = env->history.special[regid]; 217 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) 218 *dispp = env->history.gr[regid - UWX_REG_GR(4)]; 219 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 220 bsp = env->context.special[UWX_REG_BSP]; 221 regid -= UWX_REG_GR(32); 222 sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8; 223 rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f; 224 if (sor != 0 && rrb_gr != 0 && regid < sor) 225 regid = (regid + rrb_gr) % sor; 226 bsp = uwx_add_to_bsp(bsp, regid); 227 *dispp = UWX_DISP_RSTK(bsp); 228 } 229 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5)) 230 *dispp = env->history.br[regid - UWX_REG_BR(1)]; 231 else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 232 *dispp = env->history.fr[regid - UWX_REG_FR(2)]; 233 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 234 *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4]; 235 else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) || 236 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) || 237 (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) ) 238 *dispp = UWX_DISP_REG(regid); 239 else 240 status = UWX_ERR_BADREGID; 241 return status; 242} 243 244int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val) 245{ 246 int status; 247 248 if (env == 0) 249 return UWX_ERR_NOENV; 250 251 if (regid == UWX_REG_GR(12)) 252 regid = UWX_REG_SP; 253 if (regid < NSPECIALREG) { 254 env->context.special[regid] = val; 255 env->context.valid_regs |= 1 << regid; 256 status = UWX_OK; 257 } 258 else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) { 259 env->context.gr[regid - UWX_REG_GR(4)] = val; 260 env->context.valid_regs |= 261 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT); 262 status = UWX_OK; 263 } 264 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) { 265 status = UWX_ERR_BADREGID; 266 } 267 else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) { 268 env->context.br[regid - UWX_REG_BR(1)] = val; 269 env->context.valid_regs |= 270 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT); 271 status = UWX_OK; 272 } 273 else 274 status = UWX_ERR_BADREGID; 275 return status; 276} 277 278int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val) 279{ 280 281 if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5)) 282 regid -= UWX_REG_FR(2); 283 else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31)) 284 regid -= UWX_REG_FR(16) - 4; 285 else 286 return UWX_ERR_BADREGID; 287 288 env->context.fr[regid].part0 = val[0]; 289 env->context.fr[regid].part1 = val[1]; 290 env->context.valid_frs |= 1 << regid; 291 env->nsbreg = NSBREG; 292 return UWX_OK; 293} 294 295uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots) 296{ 297 int bias; 298 299 /* 300 * Here's a picture of the backing store as modeled in 301 * the computations below. "X" marks NaT collections at 302 * every 0x1f8 mod 0x200 address. 303 * 304 * To make the NaT adjustments easier, we bias the current bsp 305 * by enough slots to place it at the previous NaT collection. 306 * Then we need to add the bias to the number of slots, 307 * then add 1 for every 63 slots to account for NaT collections. 308 * Then we can remove the bias again and add the adjusted 309 * number of slots to the bsp. 310 * 311 * 0 1f8 3f8 312 * +---------------------------------------------------------------+ 313 * | X X| 314 * +---------------------------------------------------------------+ 315 * <-------- bias --------> 316 * <--- nslots ---> 317 * ^ 318 * | 319 * bsp 320 * <------- adjusted (nslots + bias) -------> 321 322 * When subtracting from bsp, we bias the bsp in the opposite 323 * direction so that it is at the next NaT collection. 324 * 325 * 0 1f8 3f8 326 * +---------------------------------------------------------------+ 327 * | X X| 328 * +---------------------------------------------------------------+ 329 * <------- bias -------> 330 * <--- nslots ---> 331 * ^ 332 * | 333 * bsp 334 * <------ adjusted (nslots + bias) ------> 335 */ 336 337 if (nslots > 0) { 338 bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ; 339 nslots += (nslots + bias) / 63; 340 } 341 else if (nslots < 0) { 342 bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ; 343 nslots -= (-nslots + bias) / 63; 344 } 345 return bsp + nslots * DWORDSZ; 346} 347