uwx_context.c revision 160157
1/*
2Copyright (c) 2003-2006 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	n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
185			natcollp, DWORDSZ, env->cb_token);
186	if (n != DWORDSZ)
187	    return UWX_ERR_COPYIN_RSTK;
188	*natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
189    }
190    else if (regid == UWX_REG_GR(0))
191	*natp = 0;
192    else
193	status = UWX_ERR_BADREGID;
194    return status;
195}
196
197int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
198{
199    int status;
200    int sor;
201    int rrb_gr;
202    uint64_t bsp;
203    int n;
204
205    if (env == 0)
206	return UWX_ERR_NOENV;
207
208    status = UWX_OK;
209
210    if (regid == UWX_REG_GR(12))
211	regid = UWX_REG_SP;
212    if (regid < NSPECIALREG) {
213	if (regid == UWX_REG_PSP || regid == UWX_REG_RP ||
214						regid == UWX_REG_PFS) {
215	    if (!(env->context.valid_regs & (1 << regid))) {
216		status = uwx_restore_markers(env);
217		if (status != UWX_OK)
218		    return status;
219	    }
220	}
221	*dispp = env->history.special[regid];
222    }
223    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
224	*dispp = env->history.gr[regid - UWX_REG_GR(4)];
225    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
226	bsp = env->context.special[UWX_REG_BSP];
227	regid -= UWX_REG_GR(32);
228	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
229	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
230	if (sor != 0 && rrb_gr != 0 && regid < sor)
231	    regid = (regid + rrb_gr) % sor;
232	bsp = uwx_add_to_bsp(bsp, regid);
233	*dispp = UWX_DISP_RSTK(bsp);
234    }
235    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
236	*dispp = env->history.br[regid - UWX_REG_BR(1)];
237    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
238	*dispp = env->history.fr[regid - UWX_REG_FR(2)];
239    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
240	*dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
241    else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
242		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
243		(regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
244	*dispp = UWX_DISP_REG(regid);
245    else
246	status = UWX_ERR_BADREGID;
247    return status;
248}
249
250int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
251{
252    int status;
253
254    if (env == 0)
255	return UWX_ERR_NOENV;
256
257    if (regid == UWX_REG_GR(12))
258	regid = UWX_REG_SP;
259    if (regid < NSPECIALREG) {
260	env->context.special[regid] = val;
261	env->context.valid_regs |= 1 << regid;
262	status = UWX_OK;
263    }
264    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
265	env->context.gr[regid - UWX_REG_GR(4)] = val;
266	env->context.valid_regs |=
267			1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
268	status = UWX_OK;
269    }
270    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
271	status = UWX_ERR_BADREGID;
272    }
273    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
274	env->context.br[regid - UWX_REG_BR(1)] = val;
275	env->context.valid_regs |=
276			1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
277	status = UWX_OK;
278    }
279    else
280	status = UWX_ERR_BADREGID;
281    return status;
282}
283
284int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
285{
286    int status;
287
288    if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
289	regid -= UWX_REG_FR(2);
290    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
291	regid -= UWX_REG_FR(16) - 4;
292    else
293	return UWX_ERR_BADREGID;
294
295    env->context.fr[regid].part0 = val[0];
296    env->context.fr[regid].part1 = val[1];
297    env->context.valid_frs |= 1 << regid;
298    env->nsbreg = NSBREG;
299    return UWX_OK;
300}
301
302uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
303{
304    int bias;
305
306    /*
307     *  Here's a picture of the backing store as modeled in
308     *  the computations below. "X" marks NaT collections at
309     *  every 0x1f8 mod 0x200 address.
310     *
311     *  To make the NaT adjustments easier, we bias the current bsp
312     *  by enough slots to place it at the previous NaT collection.
313     *  Then we need to add the bias to the number of slots,
314     *  then add 1 for every 63 slots to account for NaT collections.
315     *  Then we can remove the bias again and add the adjusted
316     *  number of slots to the bsp.
317     *
318     *   0                           1f8                             3f8
319     *  +---------------------------------------------------------------+
320     *  |                              X                               X|
321     *  +---------------------------------------------------------------+
322     *   <-------- bias -------->
323     *                           <--- nslots --->
324     *                           ^
325     *                           |
326     *                          bsp
327     *   <------------ nslots + bias ----------->
328
329     *  When subtracting from bsp, we avoid depending on the sign of
330     *  the quotient by adding 63*8 before division and subtracting 8
331     *  after division. (Assumes that we will never be called upon
332     *  to subtract more than 504 slots from bsp.)
333     *
334     *   0                           1f8                             3f8
335     *  +---------------------------------------------------------------+
336     *  |                              X                               X|
337     *  +---------------------------------------------------------------+
338     *                                  <-- bias -->
339     *                           <--- (-nslots) --->
340     *                                              ^
341     *                                              |
342     *                                             bsp
343     *                           <----------------->
344     *                             -(nslots + bias)
345     */
346
347    bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
348    nslots += (nslots + bias + 63*8) / 63 - 8;
349    return bsp + nslots * DWORDSZ;
350}
351
352int uwx_selftest_bsp_arithmetic()
353{
354    int i;
355    int j;
356    int r;
357    uint64_t bstore[161];
358    uint64_t *bsp;
359    uint64_t *p;
360    int failed = 0;
361
362    printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore);
363    r = 0;
364    bsp = bstore;
365    for (i = 0; i < 161; i++) {
366	if (((unsigned int)bsp & 0x1f8) == 0x1f8)
367	    *bsp++ = 1000 + r;
368	else
369	    *bsp++ = r++;
370    }
371
372    printf("uwx_selftest_bsp_arithmetic: plus tests...\n");
373    bsp = bstore;
374    for (i = 0; i < 64; i++) {
375	r = (int)*bsp;
376	if (r >= 1000)
377	    r -= 1000;
378	for (j = 0; j < 96; j++) {
379	    p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j);
380	    if (*p != (r + j)) {
381		failed++;
382		printf("%d [%08lx] + %d -> %08lx ",
383				i, (unsigned int)bsp, j, (unsigned int)p);
384		printf("(read %d instead of %d)\n", (int)*p, r + j);
385	    }
386	}
387	bsp++;
388    }
389
390    printf("uwx_selftest_bsp_arithmetic: minus tests...\n");
391    bsp = &bstore[161];
392    for (i = 63; i >= 0; i--) {
393	bsp--;
394	r = (int)*bsp;
395	if (r >= 1000)
396	    r -= 1000;
397	for (j = 0; j < 96; j++) {
398	    p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j);
399	    if (*p != (r - j)) {
400		failed++;
401		printf("%d [%08lx] - %d -> %08lx ",
402				i, (unsigned int)bsp, j, (unsigned int)p);
403		printf("(read %d instead of %d)\n", (int)*p, r - j);
404	    }
405	}
406    }
407
408    return failed;
409}
410