uwx_context.c revision 120925
1142425Snectar/*
255714Skris * Copyright (c) 2002,2003 Hewlett-Packard Company
355714Skris *
455714Skris * Permission is hereby granted, free of charge, to any person obtaining a
555714Skris * copy of this software and associated documentation files (the "Software"),
655714Skris * to deal in the Software without restriction, including without limitation
755714Skris * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8109998Smarkm * and/or sell copies of the Software, and to permit persons to whom the
955714Skris * Software is furnished to do so, subject to the following conditions:
1055714Skris *
1155714Skris * The above copyright notice and this permission notice shall be included
1255714Skris * in all copies or substantial portions of the Software.
1355714Skris *
1455714Skris * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1555714Skris * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1655714Skris * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1755714Skris * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1855714Skris * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1955714Skris * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2055714Skris * DEALINGS IN THE SOFTWARE.
2155714Skris */
2255714Skris
2355714Skris#include "uwx_env.h"
2455714Skris#include "uwx_context.h"
2555714Skris#include "uwx_scoreboard.h"
2655714Skris#include "uwx_step.h"
2755714Skris#include "uwx_trace.h"
2855714Skris
2955714Skrisint uwx_init_context(
3055714Skris    struct uwx_env *env,
3155714Skris    uint64_t ip,
3255714Skris    uint64_t sp,
3355714Skris    uint64_t bsp,
3455714Skris    uint64_t cfm)
3555714Skris{
3655714Skris    int i;
3755714Skris
3855714Skris    if (env == 0)
39160814Ssimon	return UWX_ERR_NOENV;
40160814Ssimon
41160814Ssimon    env->context.special[UWX_REG_IP] = ip;
42160814Ssimon    env->context.special[UWX_REG_SP] = sp;
43160814Ssimon    env->context.special[UWX_REG_BSP] = bsp;
44160814Ssimon    env->context.special[UWX_REG_CFM] = cfm;
45160814Ssimon    for (i = UWX_REG_RP; i < NSPECIALREG; i++)
46160814Ssimon	env->context.special[i] = 0;
4768651Skris    for (i = 0; i < NPRESERVEDGR; i++)
48160814Ssimon	env->context.gr[i] = 0;
49160814Ssimon    env->context.valid_regs = VALID_BASIC4;
50160814Ssimon    env->context.valid_frs = 0;
51160814Ssimon    env->rstate = 0;
52160814Ssimon    (void)uwx_init_history(env);
53160814Ssimon    return UWX_OK;
54160814Ssimon}
5555714Skris
5655714Skrisint uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
5755714Skris{
58160814Ssimon    int status;
5955714Skris    int sor;
6055714Skris    int rrb_gr;
6155714Skris    uint64_t bsp;
6255714Skris    int n;
6355714Skris
6455714Skris    if (env == 0)
6555714Skris	return UWX_ERR_NOENV;
6655714Skris
67109998Smarkm    status = UWX_OK;
6855714Skris
6955714Skris    if (regid == UWX_REG_GR(12))
7055714Skris	regid = UWX_REG_SP;
71160814Ssimon    if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
7255714Skris	*valp = env->context.special[regid];
73160814Ssimon    else if (regid == UWX_REG_PSP || regid == UWX_REG_RP ||
7455714Skris					regid == UWX_REG_PFS) {
7555714Skris	status = uwx_restore_markers(env);
76160814Ssimon	if (status != UWX_OK)
7755714Skris	    return status;
78160814Ssimon	*valp = env->context.special[regid];
79109998Smarkm    }
80109998Smarkm    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
81160814Ssimon		(env->context.valid_regs &
82109998Smarkm		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
83160814Ssimon	*valp = env->context.gr[regid - UWX_REG_GR(4)];
8455714Skris    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
8559191Skris	if (env->copyin == 0)
8655714Skris	    return UWX_ERR_NOCALLBACKS;
8755714Skris	bsp = env->context.special[UWX_REG_BSP];
8855714Skris	TRACE_C_GET_REG(regid, bsp)
8955714Skris	regid -= UWX_REG_GR(32);
9055714Skris	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
9155714Skris	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
9255714Skris	if (sor != 0 && rrb_gr != 0 && regid < sor) {
9355714Skris	    TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
9455714Skris	    regid = (regid + rrb_gr) % sor;
9555714Skris	}
9655714Skris	bsp = uwx_add_to_bsp(bsp, regid);
97160814Ssimon	n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
98160814Ssimon		    bsp, DWORDSZ, env->cb_token);
99160814Ssimon	if (n != DWORDSZ)
10055714Skris	    status = UWX_ERR_COPYIN_RSTK;
10155714Skris    }
10255714Skris    else if (regid == UWX_REG_GR(0))
10355714Skris	*valp = 0;
10455714Skris    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
10555714Skris		(env->context.valid_regs &
10655714Skris		    (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
10755714Skris	*valp = env->context.br[regid - UWX_REG_BR(1)];
10855714Skris    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) &&
10955714Skris	    (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
11055714Skris	valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
11155714Skris	valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
11255714Skris    }
11355714Skris    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) &&
114160814Ssimon	    (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) {
115160814Ssimon	valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
116160814Ssimon	valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
117160814Ssimon    }
118160814Ssimon    else if ( (regid < NSPECIALREG) ||
119160814Ssimon		(regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
120160814Ssimon		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
12155714Skris	if (env->copyin == 0)
12255714Skris	    return UWX_ERR_NOCALLBACKS;
12355714Skris	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
12459191Skris			    regid, DWORDSZ, env->cb_token);
12559191Skris	if (n != DWORDSZ)
12659191Skris	    status = UWX_ERR_COPYIN_REG;
127160814Ssimon    }
12859191Skris    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
12959191Skris	if (env->copyin == 0)
13059191Skris	    return UWX_ERR_NOCALLBACKS;
131160814Ssimon	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
13259191Skris			    regid, 2*DWORDSZ, env->cb_token);
13355714Skris	if (n != 2*DWORDSZ)
13455714Skris	    status = UWX_ERR_COPYIN_REG;
13555714Skris    }
13655714Skris    else if (regid == UWX_REG_FR(0)) {
13755714Skris	valp[0] = 0;
13855714Skris	valp[1] = 0;
13955714Skris    }
14055714Skris    else if (regid == UWX_REG_FR(1)) {
14168651Skris	valp[0] = 0x000000000000ffffULL;
14268651Skris	valp[1] = 0x8000000000000000ULL;
14368651Skris    }
14468651Skris    else
14568651Skris	status = UWX_ERR_BADREGID;
14655714Skris    return status;
14755714Skris}
14855714Skris
14955714Skrisint uwx_get_nat(struct uwx_env *env, int regid, int *natp)
15055714Skris{
15155714Skris    int status;
15255714Skris    int sor;
15355714Skris    int rrb_gr;
15455714Skris    uint64_t bsp;
15555714Skris    uint64_t natcollp;
15655714Skris    uint64_t natcoll;
15755714Skris    int n;
15855714Skris
15955714Skris    if (env == 0)
16055714Skris	return UWX_ERR_NOENV;
16155714Skris
16255714Skris    status = UWX_OK;
16355714Skris
16455714Skris    if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
16555714Skris		(env->context.valid_regs &
16655714Skris		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
167109998Smarkm	*natp = (env->context.special[UWX_REG_PRIUNAT] >>
16855714Skris				(regid - UWX_REG_GR(4)) ) & 0x01;
16955714Skris    }
17055714Skris    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
17155714Skris	if (env->copyin == 0)
17255714Skris	    return UWX_ERR_NOCALLBACKS;
17355714Skris	bsp = env->context.special[UWX_REG_BSP];
17455714Skris	regid -= UWX_REG_GR(32);
17555714Skris	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
17655714Skris	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
17755714Skris	if (sor != 0 && rrb_gr != 0 && regid < sor) {
17855714Skris	    regid = (regid + rrb_gr) % sor;
17955714Skris	}
18055714Skris	bsp = uwx_add_to_bsp(bsp, regid);
18155714Skris	natcollp = bsp | 0x01f8;
18255714Skris	if (natcollp >= bsp)
18355714Skris	    n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
18455714Skris			(uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token);
18555714Skris	else
18655714Skris	    n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
18755714Skris			bsp, DWORDSZ, env->cb_token);
18855714Skris	if (n != DWORDSZ)
18955714Skris	    return UWX_ERR_COPYIN_RSTK;
190	*natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
191    }
192    else if (regid == UWX_REG_GR(0))
193	*natp = 0;
194    else
195	status = UWX_ERR_BADREGID;
196    return status;
197}
198
199int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
200{
201    int status;
202    int sor;
203    int rrb_gr;
204    uint64_t bsp;
205
206    if (env == 0)
207	return UWX_ERR_NOENV;
208
209    status = UWX_OK;
210
211    if (regid == UWX_REG_GR(12))
212	regid = UWX_REG_SP;
213    if (regid < NSPECIALREG)
214	*dispp = env->history.special[regid];
215    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
216	*dispp = env->history.gr[regid - UWX_REG_GR(4)];
217    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
218	bsp = env->context.special[UWX_REG_BSP];
219	regid -= UWX_REG_GR(32);
220	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
221	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
222	if (sor != 0 && rrb_gr != 0 && regid < sor)
223	    regid = (regid + rrb_gr) % sor;
224	bsp = uwx_add_to_bsp(bsp, regid);
225	*dispp = UWX_DISP_RSTK(bsp);
226    }
227    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
228	*dispp = env->history.br[regid - UWX_REG_BR(1)];
229    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
230	*dispp = env->history.fr[regid - UWX_REG_FR(2)];
231    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
232	*dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
233    else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
234		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
235		(regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
236	*dispp = UWX_DISP_REG(regid);
237    else
238	status = UWX_ERR_BADREGID;
239    return status;
240}
241
242int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
243{
244    int status;
245
246    if (env == 0)
247	return UWX_ERR_NOENV;
248
249    if (regid == UWX_REG_GR(12))
250	regid = UWX_REG_SP;
251    if (regid < NSPECIALREG) {
252	env->context.special[regid] = val;
253	env->context.valid_regs |= 1 << regid;
254	status = UWX_OK;
255    }
256    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
257	env->context.gr[regid - UWX_REG_GR(4)] = val;
258	env->context.valid_regs |=
259			1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
260	status = UWX_OK;
261    }
262    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
263	status = UWX_ERR_BADREGID;
264    }
265    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
266	env->context.br[regid - UWX_REG_BR(1)] = val;
267	env->context.valid_regs |=
268			1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
269	status = UWX_OK;
270    }
271    else
272	status = UWX_ERR_BADREGID;
273    return status;
274}
275
276int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
277{
278
279    if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
280	regid -= UWX_REG_FR(2);
281    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
282	regid -= UWX_REG_FR(16) - 4;
283    else
284	return UWX_ERR_BADREGID;
285
286    env->context.fr[regid].part0 = val[0];
287    env->context.fr[regid].part1 = val[1];
288    env->context.valid_frs |= 1 << regid;
289    env->nsbreg = NSBREG;
290    return UWX_OK;
291}
292
293uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
294{
295    int bias;
296
297    /*
298     *  Here's a picture of the backing store as modeled in
299     *  the computations below. "X" marks NaT collections at
300     *  every 0x1f8 mod 0x200 address.
301     *
302     *  To make the NaT adjustments easier, we bias the current bsp
303     *  by enough slots to place it at the previous NaT collection.
304     *  Then we need to add the bias to the number of slots,
305     *  then add 1 for every 63 slots to account for NaT collections.
306     *  Then we can remove the bias again and add the adjusted
307     *  number of slots to the bsp.
308     *
309     *   0                           1f8                             3f8
310     *  +---------------------------------------------------------------+
311     *  |                              X                               X|
312     *  +---------------------------------------------------------------+
313     *   <-------- bias -------->
314     *                           <--- nslots --->
315     *                           ^
316     *                           |
317     *                          bsp
318     *   <------- adjusted (nslots + bias) ------->
319
320     *  When subtracting from bsp, we bias the bsp in the opposite
321     *  direction so that it is at the next NaT collection.
322     *
323     *   0                           1f8                             3f8
324     *  +---------------------------------------------------------------+
325     *  |                              X                               X|
326     *  +---------------------------------------------------------------+
327     *                                           <------- bias ------->
328     *                           <--- nslots --->
329     *                                           ^
330     *                                           |
331     *                                          bsp
332     *                         <------ adjusted (nslots + bias) ------>
333     */
334
335    if (nslots > 0) {
336	bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
337	nslots += (nslots + bias) / 63;
338    }
339    else if (nslots < 0) {
340	bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
341	nslots -= (-nslots + bias) / 63;
342    }
343    return bsp + nslots * DWORDSZ;
344}
345