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