uwx_context.c revision 120925
1115013Smarcel/*
2115013Smarcel * Copyright (c) 2002,2003 Hewlett-Packard Company
3115013Smarcel *
4115013Smarcel * Permission is hereby granted, free of charge, to any person obtaining a
5115013Smarcel * copy of this software and associated documentation files (the "Software"),
6115013Smarcel * to deal in the Software without restriction, including without limitation
7115013Smarcel * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8115013Smarcel * and/or sell copies of the Software, and to permit persons to whom the
9115013Smarcel * Software is furnished to do so, subject to the following conditions:
10115013Smarcel *
11115013Smarcel * The above copyright notice and this permission notice shall be included
12115013Smarcel * in all copies or substantial portions of the Software.
13115013Smarcel *
14115013Smarcel * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15115013Smarcel * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16115013Smarcel * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17115013Smarcel * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18115013Smarcel * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19115013Smarcel * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20115013Smarcel * DEALINGS IN THE SOFTWARE.
21115013Smarcel */
22115013Smarcel
23115013Smarcel#include "uwx_env.h"
24115013Smarcel#include "uwx_context.h"
25115013Smarcel#include "uwx_scoreboard.h"
26120925Smarcel#include "uwx_step.h"
27115013Smarcel#include "uwx_trace.h"
28115013Smarcel
29115013Smarcelint uwx_init_context(
30115013Smarcel    struct uwx_env *env,
31115013Smarcel    uint64_t ip,
32115013Smarcel    uint64_t sp,
33115013Smarcel    uint64_t bsp,
34115013Smarcel    uint64_t cfm)
35115013Smarcel{
36115013Smarcel    int i;
37115013Smarcel
38115013Smarcel    if (env == 0)
39115013Smarcel	return UWX_ERR_NOENV;
40115013Smarcel
41115013Smarcel    env->context.special[UWX_REG_IP] = ip;
42115013Smarcel    env->context.special[UWX_REG_SP] = sp;
43115013Smarcel    env->context.special[UWX_REG_BSP] = bsp;
44115013Smarcel    env->context.special[UWX_REG_CFM] = cfm;
45115013Smarcel    for (i = UWX_REG_RP; i < NSPECIALREG; i++)
46115013Smarcel	env->context.special[i] = 0;
47115013Smarcel    for (i = 0; i < NPRESERVEDGR; i++)
48115013Smarcel	env->context.gr[i] = 0;
49115013Smarcel    env->context.valid_regs = VALID_BASIC4;
50120925Smarcel    env->context.valid_frs = 0;
51115013Smarcel    env->rstate = 0;
52115013Smarcel    (void)uwx_init_history(env);
53115013Smarcel    return UWX_OK;
54115013Smarcel}
55115013Smarcel
56115013Smarcelint uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
57115013Smarcel{
58115013Smarcel    int status;
59115013Smarcel    int sor;
60115013Smarcel    int rrb_gr;
61115013Smarcel    uint64_t bsp;
62115013Smarcel    int n;
63115013Smarcel
64115013Smarcel    if (env == 0)
65115013Smarcel	return UWX_ERR_NOENV;
66115013Smarcel
67115013Smarcel    status = UWX_OK;
68115013Smarcel
69120925Smarcel    if (regid == UWX_REG_GR(12))
70120925Smarcel	regid = UWX_REG_SP;
71115013Smarcel    if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
72115013Smarcel	*valp = env->context.special[regid];
73120925Smarcel    else if (regid == UWX_REG_PSP || regid == UWX_REG_RP ||
74120925Smarcel					regid == UWX_REG_PFS) {
75120925Smarcel	status = uwx_restore_markers(env);
76120925Smarcel	if (status != UWX_OK)
77120925Smarcel	    return status;
78120925Smarcel	*valp = env->context.special[regid];
79120925Smarcel    }
80115013Smarcel    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
81115013Smarcel		(env->context.valid_regs &
82115013Smarcel		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
83115013Smarcel	*valp = env->context.gr[regid - UWX_REG_GR(4)];
84115013Smarcel    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
85115013Smarcel	if (env->copyin == 0)
86115013Smarcel	    return UWX_ERR_NOCALLBACKS;
87115013Smarcel	bsp = env->context.special[UWX_REG_BSP];
88115013Smarcel	TRACE_C_GET_REG(regid, bsp)
89115013Smarcel	regid -= UWX_REG_GR(32);
90115013Smarcel	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
91115013Smarcel	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
92115013Smarcel	if (sor != 0 && rrb_gr != 0 && regid < sor) {
93115013Smarcel	    TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
94115013Smarcel	    regid = (regid + rrb_gr) % sor;
95115013Smarcel	}
96115013Smarcel	bsp = uwx_add_to_bsp(bsp, regid);
97115013Smarcel	n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
98115013Smarcel		    bsp, DWORDSZ, env->cb_token);
99115013Smarcel	if (n != DWORDSZ)
100115013Smarcel	    status = UWX_ERR_COPYIN_RSTK;
101115013Smarcel    }
102115013Smarcel    else if (regid == UWX_REG_GR(0))
103115013Smarcel	*valp = 0;
104115013Smarcel    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
105115013Smarcel		(env->context.valid_regs &
106115013Smarcel		    (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
107115013Smarcel	*valp = env->context.br[regid - UWX_REG_BR(1)];
108120925Smarcel    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) &&
109120925Smarcel	    (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
110115013Smarcel	valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
111115013Smarcel	valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
112115013Smarcel    }
113120925Smarcel    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) &&
114120925Smarcel	    (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) {
115115013Smarcel	valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
116115013Smarcel	valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
117115013Smarcel    }
118115013Smarcel    else if ( (regid < NSPECIALREG) ||
119115013Smarcel		(regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
120115013Smarcel		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
121115013Smarcel	if (env->copyin == 0)
122115013Smarcel	    return UWX_ERR_NOCALLBACKS;
123115013Smarcel	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
124115013Smarcel			    regid, DWORDSZ, env->cb_token);
125115013Smarcel	if (n != DWORDSZ)
126115013Smarcel	    status = UWX_ERR_COPYIN_REG;
127115013Smarcel    }
128120925Smarcel    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
129115013Smarcel	if (env->copyin == 0)
130115013Smarcel	    return UWX_ERR_NOCALLBACKS;
131115013Smarcel	n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
132115013Smarcel			    regid, 2*DWORDSZ, env->cb_token);
133115013Smarcel	if (n != 2*DWORDSZ)
134115013Smarcel	    status = UWX_ERR_COPYIN_REG;
135115013Smarcel    }
136115013Smarcel    else if (regid == UWX_REG_FR(0)) {
137115013Smarcel	valp[0] = 0;
138115013Smarcel	valp[1] = 0;
139115013Smarcel    }
140115013Smarcel    else if (regid == UWX_REG_FR(1)) {
141115013Smarcel	valp[0] = 0x000000000000ffffULL;
142115013Smarcel	valp[1] = 0x8000000000000000ULL;
143115013Smarcel    }
144115013Smarcel    else
145115013Smarcel	status = UWX_ERR_BADREGID;
146115013Smarcel    return status;
147115013Smarcel}
148115013Smarcel
149115013Smarcelint uwx_get_nat(struct uwx_env *env, int regid, int *natp)
150115013Smarcel{
151115013Smarcel    int status;
152115013Smarcel    int sor;
153115013Smarcel    int rrb_gr;
154115013Smarcel    uint64_t bsp;
155115013Smarcel    uint64_t natcollp;
156115013Smarcel    uint64_t natcoll;
157115013Smarcel    int n;
158115013Smarcel
159115013Smarcel    if (env == 0)
160115013Smarcel	return UWX_ERR_NOENV;
161115013Smarcel
162115013Smarcel    status = UWX_OK;
163115013Smarcel
164115013Smarcel    if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
165115013Smarcel		(env->context.valid_regs &
166115013Smarcel		    (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
167115013Smarcel	*natp = (env->context.special[UWX_REG_PRIUNAT] >>
168115013Smarcel				(regid - UWX_REG_GR(4)) ) & 0x01;
169115013Smarcel    }
170115013Smarcel    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
171115013Smarcel	if (env->copyin == 0)
172115013Smarcel	    return UWX_ERR_NOCALLBACKS;
173115013Smarcel	bsp = env->context.special[UWX_REG_BSP];
174115013Smarcel	regid -= UWX_REG_GR(32);
175115013Smarcel	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
176115013Smarcel	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
177115013Smarcel	if (sor != 0 && rrb_gr != 0 && regid < sor) {
178115013Smarcel	    regid = (regid + rrb_gr) % sor;
179115013Smarcel	}
180115013Smarcel	bsp = uwx_add_to_bsp(bsp, regid);
181115013Smarcel	natcollp = bsp | 0x01f8;
182115013Smarcel	if (natcollp >= bsp)
183115013Smarcel	    n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
184120925Smarcel			(uint64_t)UWX_REG_AR_RNAT, DWORDSZ, env->cb_token);
185115013Smarcel	else
186115013Smarcel	    n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
187115013Smarcel			bsp, DWORDSZ, env->cb_token);
188115013Smarcel	if (n != DWORDSZ)
189115013Smarcel	    return UWX_ERR_COPYIN_RSTK;
190115013Smarcel	*natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
191115013Smarcel    }
192115013Smarcel    else if (regid == UWX_REG_GR(0))
193115013Smarcel	*natp = 0;
194115013Smarcel    else
195115013Smarcel	status = UWX_ERR_BADREGID;
196115013Smarcel    return status;
197115013Smarcel}
198115013Smarcel
199115013Smarcelint uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
200115013Smarcel{
201115013Smarcel    int status;
202115013Smarcel    int sor;
203115013Smarcel    int rrb_gr;
204115013Smarcel    uint64_t bsp;
205115013Smarcel
206115013Smarcel    if (env == 0)
207115013Smarcel	return UWX_ERR_NOENV;
208115013Smarcel
209115013Smarcel    status = UWX_OK;
210115013Smarcel
211120925Smarcel    if (regid == UWX_REG_GR(12))
212120925Smarcel	regid = UWX_REG_SP;
213115013Smarcel    if (regid < NSPECIALREG)
214115013Smarcel	*dispp = env->history.special[regid];
215115013Smarcel    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
216115013Smarcel	*dispp = env->history.gr[regid - UWX_REG_GR(4)];
217115013Smarcel    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
218115013Smarcel	bsp = env->context.special[UWX_REG_BSP];
219115013Smarcel	regid -= UWX_REG_GR(32);
220115013Smarcel	sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
221115013Smarcel	rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
222115013Smarcel	if (sor != 0 && rrb_gr != 0 && regid < sor)
223115013Smarcel	    regid = (regid + rrb_gr) % sor;
224115013Smarcel	bsp = uwx_add_to_bsp(bsp, regid);
225115013Smarcel	*dispp = UWX_DISP_RSTK(bsp);
226115013Smarcel    }
227115013Smarcel    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
228115013Smarcel	*dispp = env->history.br[regid - UWX_REG_BR(1)];
229115013Smarcel    else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
230115013Smarcel	*dispp = env->history.fr[regid - UWX_REG_FR(2)];
231115013Smarcel    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
232115013Smarcel	*dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
233115013Smarcel    else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
234115013Smarcel		(regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
235115013Smarcel		(regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
236115013Smarcel	*dispp = UWX_DISP_REG(regid);
237115013Smarcel    else
238115013Smarcel	status = UWX_ERR_BADREGID;
239115013Smarcel    return status;
240115013Smarcel}
241115013Smarcel
242115013Smarcelint uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
243115013Smarcel{
244115013Smarcel    int status;
245115013Smarcel
246115013Smarcel    if (env == 0)
247115013Smarcel	return UWX_ERR_NOENV;
248115013Smarcel
249120925Smarcel    if (regid == UWX_REG_GR(12))
250120925Smarcel	regid = UWX_REG_SP;
251115013Smarcel    if (regid < NSPECIALREG) {
252115013Smarcel	env->context.special[regid] = val;
253115013Smarcel	env->context.valid_regs |= 1 << regid;
254115013Smarcel	status = UWX_OK;
255115013Smarcel    }
256115013Smarcel    else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
257115013Smarcel	env->context.gr[regid - UWX_REG_GR(4)] = val;
258115013Smarcel	env->context.valid_regs |=
259115013Smarcel			1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
260115013Smarcel	status = UWX_OK;
261115013Smarcel    }
262115013Smarcel    else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
263115013Smarcel	status = UWX_ERR_BADREGID;
264115013Smarcel    }
265115013Smarcel    else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
266115013Smarcel	env->context.br[regid - UWX_REG_BR(1)] = val;
267115013Smarcel	env->context.valid_regs |=
268115013Smarcel			1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
269115013Smarcel	status = UWX_OK;
270115013Smarcel    }
271115013Smarcel    else
272115013Smarcel	status = UWX_ERR_BADREGID;
273115013Smarcel    return status;
274115013Smarcel}
275115013Smarcel
276115013Smarcelint uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
277115013Smarcel{
278115013Smarcel
279115013Smarcel    if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
280115013Smarcel	regid -= UWX_REG_FR(2);
281115013Smarcel    else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
282115013Smarcel	regid -= UWX_REG_FR(16) - 4;
283115013Smarcel    else
284115013Smarcel	return UWX_ERR_BADREGID;
285115013Smarcel
286115013Smarcel    env->context.fr[regid].part0 = val[0];
287115013Smarcel    env->context.fr[regid].part1 = val[1];
288115013Smarcel    env->context.valid_frs |= 1 << regid;
289115013Smarcel    env->nsbreg = NSBREG;
290115013Smarcel    return UWX_OK;
291115013Smarcel}
292115013Smarcel
293115013Smarceluint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
294115013Smarcel{
295115013Smarcel    int bias;
296115013Smarcel
297115013Smarcel    /*
298115013Smarcel     *  Here's a picture of the backing store as modeled in
299115013Smarcel     *  the computations below. "X" marks NaT collections at
300115013Smarcel     *  every 0x1f8 mod 0x200 address.
301115013Smarcel     *
302115013Smarcel     *  To make the NaT adjustments easier, we bias the current bsp
303115013Smarcel     *  by enough slots to place it at the previous NaT collection.
304115013Smarcel     *  Then we need to add the bias to the number of slots,
305115013Smarcel     *  then add 1 for every 63 slots to account for NaT collections.
306115013Smarcel     *  Then we can remove the bias again and add the adjusted
307115013Smarcel     *  number of slots to the bsp.
308115013Smarcel     *
309115013Smarcel     *   0                           1f8                             3f8
310115013Smarcel     *  +---------------------------------------------------------------+
311115013Smarcel     *  |                              X                               X|
312115013Smarcel     *  +---------------------------------------------------------------+
313115013Smarcel     *   <-------- bias -------->
314115013Smarcel     *                           <--- nslots --->
315115013Smarcel     *                           ^
316115013Smarcel     *                           |
317115013Smarcel     *                          bsp
318115013Smarcel     *   <------- adjusted (nslots + bias) ------->
319115013Smarcel
320115013Smarcel     *  When subtracting from bsp, we bias the bsp in the opposite
321115013Smarcel     *  direction so that it is at the next NaT collection.
322115013Smarcel     *
323115013Smarcel     *   0                           1f8                             3f8
324115013Smarcel     *  +---------------------------------------------------------------+
325115013Smarcel     *  |                              X                               X|
326115013Smarcel     *  +---------------------------------------------------------------+
327115013Smarcel     *                                           <------- bias ------->
328115013Smarcel     *                           <--- nslots --->
329115013Smarcel     *                                           ^
330115013Smarcel     *                                           |
331115013Smarcel     *                                          bsp
332115013Smarcel     *                         <------ adjusted (nslots + bias) ------>
333115013Smarcel     */
334115013Smarcel
335115013Smarcel    if (nslots > 0) {
336115013Smarcel	bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
337115013Smarcel	nslots += (nslots + bias) / 63;
338115013Smarcel    }
339115013Smarcel    else if (nslots < 0) {
340115013Smarcel	bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
341115013Smarcel	nslots -= (-nslots + bias) / 63;
342115013Smarcel    }
343115013Smarcel    return bsp + nslots * DWORDSZ;
344115013Smarcel}
345