2 Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
26 #include "uwx_scoreboard.h"
28 #include "uwx_trace.h"
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;
53 (void)uwx_init_history(env);
57 int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
70 if (regid == UWX_REG_GR(12))
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);
79 *valp = env->context.special[regid];
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)) {
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;
97 bsp = uwx_add_to_bsp(bsp, regid);
98 n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
99 bsp, DWORDSZ, env->cb_token);
101 status = UWX_ERR_COPYIN_RSTK;
103 else if (regid == UWX_REG_GR(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;
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;
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);
127 status = UWX_ERR_COPYIN_REG;
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);
135 status = UWX_ERR_COPYIN_REG;
137 else if (regid == UWX_REG_FR(0)) {
141 else if (regid == UWX_REG_FR(1)) {
142 valp[0] = 0x000000000000ffffULL;
143 valp[1] = 0x8000000000000000ULL;
146 status = UWX_ERR_BADREGID;
150 int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
161 return UWX_ERR_NOENV;
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;
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;
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);
186 return UWX_ERR_COPYIN_RSTK;
187 *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
189 else if (regid == UWX_REG_GR(0))
192 status = UWX_ERR_BADREGID;
196 int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
204 return UWX_ERR_NOENV;
208 if (regid == UWX_REG_GR(12))
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)
219 *dispp = env->history.special[regid];
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);
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);
244 status = UWX_ERR_BADREGID;
248 int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
253 return UWX_ERR_NOENV;
255 if (regid == UWX_REG_GR(12))
257 if (regid < NSPECIALREG) {
258 env->context.special[regid] = val;
259 env->context.valid_regs |= 1 << regid;
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);
268 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
269 status = UWX_ERR_BADREGID;
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);
278 status = UWX_ERR_BADREGID;
282 int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
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;
290 return UWX_ERR_BADREGID;
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;
299 uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
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.
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.
316 * +---------------------------------------------------------------+
318 * +---------------------------------------------------------------+
319 * <-------- bias -------->
324 * <------------ nslots + bias ----------->
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.)
332 * +---------------------------------------------------------------+
334 * +---------------------------------------------------------------+
336 * <--- (-nslots) --->
340 * <----------------->
344 bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
345 nslots += (nslots + bias + 63*8) / 63 - 8;
346 return bsp + nslots * DWORDSZ;
350 int uwx_selftest_bsp_arithmetic()
355 uint64_t bstore[161];
360 printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore);
363 for (i = 0; i < 161; i++) {
364 if (((unsigned int)bsp & 0x1f8) == 0x1f8)
370 printf("uwx_selftest_bsp_arithmetic: plus tests...\n");
372 for (i = 0; i < 64; i++) {
376 for (j = 0; j < 96; j++) {
377 p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j);
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);
388 printf("uwx_selftest_bsp_arithmetic: minus tests...\n");
390 for (i = 63; i >= 0; i--) {
395 for (j = 0; j < 96; j++) {
396 p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j);
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);