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