1 /*
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
10 conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
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.
23 */
24
25 #include "uwx_env.h"
26 #include "uwx_scoreboard.h"
27 #include "uwx_step.h"
28 #include "uwx_trace.h"
29
uwx_init_context(struct uwx_env * env,uint64_t ip,uint64_t sp,uint64_t bsp,uint64_t cfm)30 int uwx_init_context(
31 struct uwx_env *env,
32 uint64_t ip,
33 uint64_t sp,
34 uint64_t bsp,
35 uint64_t cfm)
36 {
37 int i;
38
39 if (env == 0)
40 return UWX_ERR_NOENV;
41
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;
52 env->rstate = 0;
53 (void)uwx_init_history(env);
54 return UWX_OK;
55 }
56
uwx_get_reg(struct uwx_env * env,int regid,uint64_t * valp)57 int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
58 {
59 int status;
60 int sor;
61 int rrb_gr;
62 uint64_t bsp;
63 int n;
64
65 if (env == 0)
66 return UWX_ERR_NOENV;
67
68 status = UWX_OK;
69
70 if (regid == UWX_REG_GR(12))
71 regid = UWX_REG_SP;
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);
77 if (status != UWX_OK)
78 return status;
79 *valp = env->context.special[regid];
80 }
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)) {
86 if (env->copyin == 0)
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;
96 }
97 bsp = uwx_add_to_bsp(bsp, regid);
98 n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
99 bsp, DWORDSZ, env->cb_token);
100 if (n != DWORDSZ)
101 status = UWX_ERR_COPYIN_RSTK;
102 }
103 else if (regid == UWX_REG_GR(0))
104 *valp = 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;
113 }
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;
118 }
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);
126 if (n != DWORDSZ)
127 status = UWX_ERR_COPYIN_REG;
128 }
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);
134 if (n != 2*DWORDSZ)
135 status = UWX_ERR_COPYIN_REG;
136 }
137 else if (regid == UWX_REG_FR(0)) {
138 valp[0] = 0;
139 valp[1] = 0;
140 }
141 else if (regid == UWX_REG_FR(1)) {
142 valp[0] = 0x000000000000ffffULL;
143 valp[1] = 0x8000000000000000ULL;
144 }
145 else
146 status = UWX_ERR_BADREGID;
147 return status;
148 }
149
uwx_get_nat(struct uwx_env * env,int regid,int * natp)150 int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
151 {
152 int status;
153 int sor;
154 int rrb_gr;
155 uint64_t bsp;
156 uint64_t natcollp;
157 uint64_t natcoll;
158 int n;
159
160 if (env == 0)
161 return UWX_ERR_NOENV;
162
163 status = UWX_OK;
164
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;
170 }
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;
180 }
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);
185 if (n != DWORDSZ)
186 return UWX_ERR_COPYIN_RSTK;
187 *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
188 }
189 else if (regid == UWX_REG_GR(0))
190 *natp = 0;
191 else
192 status = UWX_ERR_BADREGID;
193 return status;
194 }
195
uwx_get_spill_loc(struct uwx_env * env,int regid,uint64_t * dispp)196 int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
197 {
198 int status;
199 int sor;
200 int rrb_gr;
201 uint64_t bsp;
202
203 if (env == 0)
204 return UWX_ERR_NOENV;
205
206 status = UWX_OK;
207
208 if (regid == UWX_REG_GR(12))
209 regid = UWX_REG_SP;
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)
216 return status;
217 }
218 }
219 *dispp = env->history.special[regid];
220 }
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);
232 }
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);
243 else
244 status = UWX_ERR_BADREGID;
245 return status;
246 }
247
uwx_set_reg(struct uwx_env * env,int regid,uint64_t val)248 int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
249 {
250 int status;
251
252 if (env == 0)
253 return UWX_ERR_NOENV;
254
255 if (regid == UWX_REG_GR(12))
256 regid = UWX_REG_SP;
257 if (regid < NSPECIALREG) {
258 env->context.special[regid] = val;
259 env->context.valid_regs |= 1 << regid;
260 status = UWX_OK;
261 }
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);
266 status = UWX_OK;
267 }
268 else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
269 status = UWX_ERR_BADREGID;
270 }
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);
275 status = UWX_OK;
276 }
277 else
278 status = UWX_ERR_BADREGID;
279 return status;
280 }
281
uwx_set_fr(struct uwx_env * env,int regid,uint64_t * val)282 int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
283 {
284
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;
289 else
290 return UWX_ERR_BADREGID;
291
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;
296 return UWX_OK;
297 }
298
uwx_add_to_bsp(uint64_t bsp,int nslots)299 uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
300 {
301 int bias;
302
303 /*
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.
307 *
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.
314 *
315 * 0 1f8 3f8
316 * +---------------------------------------------------------------+
317 * | X X|
318 * +---------------------------------------------------------------+
319 * <-------- bias -------->
320 * <--- nslots --->
321 * ^
322 * |
323 * bsp
324 * <------------ nslots + bias ----------->
325
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.)
330 *
331 * 0 1f8 3f8
332 * +---------------------------------------------------------------+
333 * | X X|
334 * +---------------------------------------------------------------+
335 * <-- bias -->
336 * <--- (-nslots) --->
337 * ^
338 * |
339 * bsp
340 * <----------------->
341 * -(nslots + bias)
342 */
343
344 bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
345 nslots += (nslots + bias + 63*8) / 63 - 8;
346 return bsp + nslots * DWORDSZ;
347 }
348
349 #if 0
350 int uwx_selftest_bsp_arithmetic()
351 {
352 int i;
353 int j;
354 int r;
355 uint64_t bstore[161];
356 uint64_t *bsp;
357 uint64_t *p;
358 int failed = 0;
359
360 printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore);
361 r = 0;
362 bsp = bstore;
363 for (i = 0; i < 161; i++) {
364 if (((unsigned int)bsp & 0x1f8) == 0x1f8)
365 *bsp++ = 1000 + r;
366 else
367 *bsp++ = r++;
368 }
369
370 printf("uwx_selftest_bsp_arithmetic: plus tests...\n");
371 bsp = bstore;
372 for (i = 0; i < 64; i++) {
373 r = (int)*bsp;
374 if (r >= 1000)
375 r -= 1000;
376 for (j = 0; j < 96; j++) {
377 p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j);
378 if (*p != (r + j)) {
379 failed++;
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);
383 }
384 }
385 bsp++;
386 }
387
388 printf("uwx_selftest_bsp_arithmetic: minus tests...\n");
389 bsp = &bstore[161];
390 for (i = 63; i >= 0; i--) {
391 bsp--;
392 r = (int)*bsp;
393 if (r >= 1000)
394 r -= 1000;
395 for (j = 0; j < 96; j++) {
396 p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j);
397 if (*p != (r - j)) {
398 failed++;
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);
402 }
403 }
404 }
405
406 return failed;
407 }
408 #endif
409