uwx_context.c revision 115013
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_trace.h"
27
28int uwx_init_context(
29    struct uwx_env *env,
30    uint64_t ip,
31    uint64_t sp,
32    uint64_t bsp,
33    uint64_t cfm)
34{
35    int i;
36
37    if (env == 0)
38	return UWX_ERR_NOENV;
39
40    env->context.special[UWX_REG_IP] = ip;
41    env->context.special[UWX_REG_SP] = sp;
42    env->context.special[UWX_REG_BSP] = bsp;
43    env->context.special[UWX_REG_CFM] = cfm;
44    for (i = UWX_REG_RP; i < NSPECIALREG; i++)
45	env->context.special[i] = 0;
46    for (i = 0; i < NPRESERVEDGR; i++)
47	env->context.gr[i] = 0;
48    env->context.valid_regs = VALID_BASIC4;
49    env->rstate = 0;
50    (void)uwx_init_history(env);
51    return UWX_OK;
52}
53
54int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
55{
56    int status;
57    int sor;
58    int rrb_gr;
59    uint64_t bsp;
60    int n;
61
62    if (env == 0)
63	return UWX_ERR_NOENV;
64
65    status = UWX_OK;
66
67    if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
68	*valp = env->context.special[regid];
69    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
70		(env->context.valid_regs &
71		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
72	*valp = env->context.gr[regid - UWX_REG_GR(4)];
73    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
74	if (env->copyin == 0)
75	    return UWX_ERR_NOCALLBACKS;
76	bsp = env->context.special[UWX_REG_BSP];
77	TRACE_C_GET_REG(regid, bsp)
78	regid -= UWX_REG_GR(32);
79	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
80	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
81	if (sor != 0 && rrb_gr != 0 && regid < sor) {
82	    TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
83	    regid = (regid + rrb_gr) % sor;
84	}
85	bsp = uwx_add_to_bsp(bsp, regid);
86	n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
87		    bsp, DWORDSZ, env->cb_token);
88	if (n != DWORDSZ)
89	    status = UWX_ERR_COPYIN_RSTK;
90    }
91    else if (regid == UWX_REG_GR(0))
92	*valp = 0;
93    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
94		(env->context.valid_regs &
95		    (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
96	*valp = env->context.br[regid - UWX_REG_BR(1)];
97    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(5) &&
98		(env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
99	valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
100	valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
101    }
102    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_BR(31) &&
103		(env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
104	valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
105	valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
106    }
107    else if ( (regid < NSPECIALREG) ||
108		(regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
109		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
110	if (env->copyin == 0)
111	    return UWX_ERR_NOCALLBACKS;
112	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
113			    regid, DWORDSZ, env->cb_token);
114	if (n != DWORDSZ)
115	    status = UWX_ERR_COPYIN_REG;
116    }
117    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(127)) {
118	if (env->copyin == 0)
119	    return UWX_ERR_NOCALLBACKS;
120	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
121			    regid, 2*DWORDSZ, env->cb_token);
122	if (n != 2*DWORDSZ)
123	    status = UWX_ERR_COPYIN_REG;
124    }
125    else if (regid == UWX_REG_FR(0)) {
126	valp[0] = 0;
127	valp[1] = 0;
128    }
129    else if (regid == UWX_REG_FR(1)) {
130	valp[0] = 0x000000000000ffffULL;
131	valp[1] = 0x8000000000000000ULL;
132    }
133    else
134	status = UWX_ERR_BADREGID;
135    return status;
136}
137
138int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
139{
140    int status;
141    int sor;
142    int rrb_gr;
143    uint64_t bsp;
144    uint64_t natcollp;
145    uint64_t natcoll;
146    int n;
147
148    if (env == 0)
149	return UWX_ERR_NOENV;
150
151    status = UWX_OK;
152
153    if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
154		(env->context.valid_regs &
155		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
156	*natp = (env->context.special[UWX_REG_PRIUNAT] >>
157				(regid - UWX_REG_GR(4)) ) & 0x01;
158    }
159    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
160	if (env->copyin == 0)
161	    return UWX_ERR_NOCALLBACKS;
162	bsp = env->context.special[UWX_REG_BSP];
163	regid -= UWX_REG_GR(32);
164	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
165	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
166	if (sor != 0 && rrb_gr != 0 && regid < sor) {
167	    regid = (regid + rrb_gr) % sor;
168	}
169	bsp = uwx_add_to_bsp(bsp, regid);
170	natcollp = bsp | 0x01f8;
171	if (natcollp >= bsp)
172	    n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
173			(uint64_t)UWX_REG_RNAT, DWORDSZ, env->cb_token);
174	else
175	    n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
176			bsp, DWORDSZ, env->cb_token);
177	if (n != DWORDSZ)
178	    return UWX_ERR_COPYIN_RSTK;
179	*natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
180    }
181    else if (regid == UWX_REG_GR(0))
182	*natp = 0;
183    else
184	status = UWX_ERR_BADREGID;
185    return status;
186}
187
188int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
189{
190    int status;
191    int sor;
192    int rrb_gr;
193    uint64_t bsp;
194
195    if (env == 0)
196	return UWX_ERR_NOENV;
197
198    status = UWX_OK;
199
200    if (regid < NSPECIALREG)
201	*dispp = env->history.special[regid];
202    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
203	*dispp = env->history.gr[regid - UWX_REG_GR(4)];
204    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
205	bsp = env->context.special[UWX_REG_BSP];
206	regid -= UWX_REG_GR(32);
207	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
208	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
209	if (sor != 0 && rrb_gr != 0 && regid < sor)
210	    regid = (regid + rrb_gr) % sor;
211	bsp = uwx_add_to_bsp(bsp, regid);
212	*dispp = UWX_DISP_RSTK(bsp);
213    }
214    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
215	*dispp = env->history.br[regid - UWX_REG_BR(1)];
216    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
217	*dispp = env->history.fr[regid - UWX_REG_FR(2)];
218    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
219	*dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
220    else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
221		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
222		(regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
223	*dispp = UWX_DISP_REG(regid);
224    else
225	status = UWX_ERR_BADREGID;
226    return status;
227}
228
229int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
230{
231    int status;
232
233    if (env == 0)
234	return UWX_ERR_NOENV;
235
236    if (regid < NSPECIALREG) {
237	env->context.special[regid] = val;
238	env->context.valid_regs |= 1 << regid;
239	status = UWX_OK;
240    }
241    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
242	env->context.gr[regid - UWX_REG_GR(4)] = val;
243	env->context.valid_regs |=
244			1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
245	status = UWX_OK;
246    }
247    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
248	status = UWX_ERR_BADREGID;
249    }
250    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
251	env->context.br[regid - UWX_REG_BR(1)] = val;
252	env->context.valid_regs |=
253			1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
254	status = UWX_OK;
255    }
256    else
257	status = UWX_ERR_BADREGID;
258    return status;
259}
260
261int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
262{
263
264    if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
265	regid -= UWX_REG_FR(2);
266    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
267	regid -= UWX_REG_FR(16) - 4;
268    else
269	return UWX_ERR_BADREGID;
270
271    env->context.fr[regid].part0 = val[0];
272    env->context.fr[regid].part1 = val[1];
273    env->context.valid_frs |= 1 << regid;
274    env->nsbreg = NSBREG;
275    return UWX_OK;
276}
277
278uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
279{
280    int bias;
281
282    /*
283     *  Here's a picture of the backing store as modeled in
284     *  the computations below. "X" marks NaT collections at
285     *  every 0x1f8 mod 0x200 address.
286     *
287     *  To make the NaT adjustments easier, we bias the current bsp
288     *  by enough slots to place it at the previous NaT collection.
289     *  Then we need to add the bias to the number of slots,
290     *  then add 1 for every 63 slots to account for NaT collections.
291     *  Then we can remove the bias again and add the adjusted
292     *  number of slots to the bsp.
293     *
294     *   0                           1f8                             3f8
295     *  +---------------------------------------------------------------+
296     *  |                              X                               X|
297     *  +---------------------------------------------------------------+
298     *   <-------- bias -------->
299     *                           <--- nslots --->
300     *                           ^
301     *                           |
302     *                          bsp
303     *   <------- adjusted (nslots + bias) ------->
304
305     *  When subtracting from bsp, we bias the bsp in the opposite
306     *  direction so that it is at the next NaT collection.
307     *
308     *   0                           1f8                             3f8
309     *  +---------------------------------------------------------------+
310     *  |                              X                               X|
311     *  +---------------------------------------------------------------+
312     *                                           <------- bias ------->
313     *                           <--- nslots --->
314     *                                           ^
315     *                                           |
316     *                                          bsp
317     *                         <------ adjusted (nslots + bias) ------>
318     */
319
320    if (nslots > 0) {
321	bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
322	nslots += (nslots + bias) / 63;
323    }
324    else if (nslots < 0) {
325	bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
326	nslots -= (-nslots + bias) / 63;
327    }
328    return bsp + nslots * DWORDSZ;
329}
330