]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/ia64/libuwx/src/uwx_context.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / ia64 / libuwx / src / uwx_context.c
1 /*
2 Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
10 conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "uwx_env.h"
26 #include "uwx_scoreboard.h"
27 #include "uwx_step.h"
28 #include "uwx_trace.h"
29
30 int uwx_init_context(
31     struct uwx_env *env,
32     uint64_t ip,
33     uint64_t sp,
34     uint64_t bsp,
35     uint64_t cfm)
36 {
37     int i;
38
39     if (env == 0)
40         return UWX_ERR_NOENV;
41
42     env->context.special[UWX_REG_IP] = ip;
43     env->context.special[UWX_REG_SP] = sp;
44     env->context.special[UWX_REG_BSP] = bsp;
45     env->context.special[UWX_REG_CFM] = cfm;
46     for (i = UWX_REG_RP; i < NSPECIALREG; i++)
47         env->context.special[i] = 0;
48     for (i = 0; i < NPRESERVEDGR; i++)
49         env->context.gr[i] = 0;
50     env->context.valid_regs = VALID_BASIC4;
51     env->context.valid_frs = 0;
52     env->rstate = 0;
53     (void)uwx_init_history(env);
54     return UWX_OK;
55 }
56
57 int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
58 {
59     int status;
60     int sor;
61     int rrb_gr;
62     uint64_t bsp;
63     int n;
64
65     if (env == 0)
66         return UWX_ERR_NOENV;
67
68     status = UWX_OK;
69
70     if (regid == UWX_REG_GR(12))
71         regid = UWX_REG_SP;
72     if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
73         *valp = env->context.special[regid];
74     else if (regid == UWX_REG_PSP || regid == UWX_REG_RP ||
75                                         regid == UWX_REG_PFS) {
76         status = uwx_restore_markers(env);
77         if (status != UWX_OK)
78             return status;
79         *valp = env->context.special[regid];
80     }
81     else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
82                 (env->context.valid_regs &
83                     (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
84         *valp = env->context.gr[regid - UWX_REG_GR(4)];
85     else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
86         if (env->copyin == 0)
87             return UWX_ERR_NOCALLBACKS;
88         bsp = env->context.special[UWX_REG_BSP];
89         TRACE_C_GET_REG(regid, bsp)
90         regid -= UWX_REG_GR(32);
91         sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
92         rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
93         if (sor != 0 && rrb_gr != 0 && regid < sor) {
94             TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
95             regid = (regid + rrb_gr) % sor;
96         }
97         bsp = uwx_add_to_bsp(bsp, regid);
98         n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
99                     bsp, DWORDSZ, env->cb_token);
100         if (n != DWORDSZ)
101             status = UWX_ERR_COPYIN_RSTK;
102     }
103     else if (regid == UWX_REG_GR(0))
104         *valp = 0;
105     else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
106                 (env->context.valid_regs &
107                     (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
108         *valp = env->context.br[regid - UWX_REG_BR(1)];
109     else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5) &&
110             (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
111         valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
112         valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
113     }
114     else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31) &&
115             (env->context.valid_frs & (1 << (regid - UWX_REG_FR(16) + 4))) ) {
116         valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
117         valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
118     }
119     else if ( (regid < NSPECIALREG) ||
120                 (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
121                 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
122         if (env->copyin == 0)
123             return UWX_ERR_NOCALLBACKS;
124         n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
125                             regid, DWORDSZ, env->cb_token);
126         if (n != DWORDSZ)
127             status = UWX_ERR_COPYIN_REG;
128     }
129     else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) {
130         if (env->copyin == 0)
131             return UWX_ERR_NOCALLBACKS;
132         n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
133                             regid, 2*DWORDSZ, env->cb_token);
134         if (n != 2*DWORDSZ)
135             status = UWX_ERR_COPYIN_REG;
136     }
137     else if (regid == UWX_REG_FR(0)) {
138         valp[0] = 0;
139         valp[1] = 0;
140     }
141     else if (regid == UWX_REG_FR(1)) {
142         valp[0] = 0x000000000000ffffULL;
143         valp[1] = 0x8000000000000000ULL;
144     }
145     else
146         status = UWX_ERR_BADREGID;
147     return status;
148 }
149
150 int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
151 {
152     int status;
153     int sor;
154     int rrb_gr;
155     uint64_t bsp;
156     uint64_t natcollp;
157     uint64_t natcoll;
158     int n;
159
160     if (env == 0)
161         return UWX_ERR_NOENV;
162
163     status = UWX_OK;
164
165     if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
166                 (env->context.valid_regs &
167                     (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
168         *natp = (env->context.special[UWX_REG_PRIUNAT] >>
169                                 (regid - UWX_REG_GR(4)) ) & 0x01;
170     }
171     else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
172         if (env->copyin == 0)
173             return UWX_ERR_NOCALLBACKS;
174         bsp = env->context.special[UWX_REG_BSP];
175         regid -= UWX_REG_GR(32);
176         sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
177         rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
178         if (sor != 0 && rrb_gr != 0 && regid < sor) {
179             regid = (regid + rrb_gr) % sor;
180         }
181         bsp = uwx_add_to_bsp(bsp, regid);
182         natcollp = bsp | 0x01f8;
183         n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
184                         natcollp, DWORDSZ, env->cb_token);
185         if (n != DWORDSZ)
186             return UWX_ERR_COPYIN_RSTK;
187         *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
188     }
189     else if (regid == UWX_REG_GR(0))
190         *natp = 0;
191     else
192         status = UWX_ERR_BADREGID;
193     return status;
194 }
195
196 int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
197 {
198     int status;
199     int sor;
200     int rrb_gr;
201     uint64_t bsp;
202
203     if (env == 0)
204         return UWX_ERR_NOENV;
205
206     status = UWX_OK;
207
208     if (regid == UWX_REG_GR(12))
209         regid = UWX_REG_SP;
210     if (regid < NSPECIALREG) {
211         if (regid == UWX_REG_PSP || regid == UWX_REG_RP ||
212                                                 regid == UWX_REG_PFS) {
213             if (!(env->context.valid_regs & (1 << regid))) {
214                 status = uwx_restore_markers(env);
215                 if (status != UWX_OK)
216                     return status;
217             }
218         }
219         *dispp = env->history.special[regid];
220     }
221     else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
222         *dispp = env->history.gr[regid - UWX_REG_GR(4)];
223     else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
224         bsp = env->context.special[UWX_REG_BSP];
225         regid -= UWX_REG_GR(32);
226         sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
227         rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
228         if (sor != 0 && rrb_gr != 0 && regid < sor)
229             regid = (regid + rrb_gr) % sor;
230         bsp = uwx_add_to_bsp(bsp, regid);
231         *dispp = UWX_DISP_RSTK(bsp);
232     }
233     else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
234         *dispp = env->history.br[regid - UWX_REG_BR(1)];
235     else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
236         *dispp = env->history.fr[regid - UWX_REG_FR(2)];
237     else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
238         *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
239     else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
240                 (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
241                 (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
242         *dispp = UWX_DISP_REG(regid);
243     else
244         status = UWX_ERR_BADREGID;
245     return status;
246 }
247
248 int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
249 {
250     int status;
251
252     if (env == 0)
253         return UWX_ERR_NOENV;
254
255     if (regid == UWX_REG_GR(12))
256         regid = UWX_REG_SP;
257     if (regid < NSPECIALREG) {
258         env->context.special[regid] = val;
259         env->context.valid_regs |= 1 << regid;
260         status = UWX_OK;
261     }
262     else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
263         env->context.gr[regid - UWX_REG_GR(4)] = val;
264         env->context.valid_regs |=
265                         1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
266         status = UWX_OK;
267     }
268     else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
269         status = UWX_ERR_BADREGID;
270     }
271     else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
272         env->context.br[regid - UWX_REG_BR(1)] = val;
273         env->context.valid_regs |=
274                         1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
275         status = UWX_OK;
276     }
277     else
278         status = UWX_ERR_BADREGID;
279     return status;
280 }
281
282 int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
283 {
284
285     if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
286         regid -= UWX_REG_FR(2);
287     else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
288         regid -= UWX_REG_FR(16) - 4;
289     else
290         return UWX_ERR_BADREGID;
291
292     env->context.fr[regid].part0 = val[0];
293     env->context.fr[regid].part1 = val[1];
294     env->context.valid_frs |= 1 << regid;
295     env->nsbreg = NSBREG;
296     return UWX_OK;
297 }
298
299 uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
300 {
301     int bias;
302
303     /*
304      *  Here's a picture of the backing store as modeled in
305      *  the computations below. "X" marks NaT collections at
306      *  every 0x1f8 mod 0x200 address.
307      *
308      *  To make the NaT adjustments easier, we bias the current bsp
309      *  by enough slots to place it at the previous NaT collection.
310      *  Then we need to add the bias to the number of slots,
311      *  then add 1 for every 63 slots to account for NaT collections.
312      *  Then we can remove the bias again and add the adjusted
313      *  number of slots to the bsp.
314      *
315      *   0                           1f8                             3f8
316      *  +---------------------------------------------------------------+
317      *  |                              X                               X|
318      *  +---------------------------------------------------------------+
319      *   <-------- bias -------->
320      *                           <--- nslots --->
321      *                           ^
322      *                           |
323      *                          bsp
324      *   <------------ nslots + bias ----------->
325
326      *  When subtracting from bsp, we avoid depending on the sign of
327      *  the quotient by adding 63*8 before division and subtracting 8
328      *  after division. (Assumes that we will never be called upon
329      *  to subtract more than 504 slots from bsp.)
330      *
331      *   0                           1f8                             3f8
332      *  +---------------------------------------------------------------+
333      *  |                              X                               X|
334      *  +---------------------------------------------------------------+
335      *                                  <-- bias -->
336      *                           <--- (-nslots) --->
337      *                                              ^
338      *                                              |
339      *                                             bsp
340      *                           <----------------->
341      *                             -(nslots + bias)
342      */
343
344     bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
345     nslots += (nslots + bias + 63*8) / 63 - 8;
346     return bsp + nslots * DWORDSZ;
347 }
348
349 #if 0
350 int uwx_selftest_bsp_arithmetic()
351 {
352     int i;
353     int j;
354     int r;
355     uint64_t bstore[161];
356     uint64_t *bsp;
357     uint64_t *p;
358     int failed = 0;
359
360     printf("uwx_selftest_bsp_arithmetic: bsp at %08lx\n", (unsigned int)bstore);
361     r = 0;
362     bsp = bstore;
363     for (i = 0; i < 161; i++) {
364         if (((unsigned int)bsp & 0x1f8) == 0x1f8)
365             *bsp++ = 1000 + r;
366         else
367             *bsp++ = r++;
368     }
369
370     printf("uwx_selftest_bsp_arithmetic: plus tests...\n");
371     bsp = bstore;
372     for (i = 0; i < 64; i++) {
373         r = (int)*bsp;
374         if (r >= 1000)
375             r -= 1000;
376         for (j = 0; j < 96; j++) {
377             p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, j);
378             if (*p != (r + j)) {
379                 failed++;
380                 printf("%d [%08lx] + %d -> %08lx ",
381                                 i, (unsigned int)bsp, j, (unsigned int)p);
382                 printf("(read %d instead of %d)\n", (int)*p, r + j);
383             }
384         }
385         bsp++;
386     }
387
388     printf("uwx_selftest_bsp_arithmetic: minus tests...\n");
389     bsp = &bstore[161];
390     for (i = 63; i >= 0; i--) {
391         bsp--;
392         r = (int)*bsp;
393         if (r >= 1000)
394             r -= 1000;
395         for (j = 0; j < 96; j++) {
396             p = (uint64_t *)(intptr_t)uwx_add_to_bsp((uint64_t)bsp, -j);
397             if (*p != (r - j)) {
398                 failed++;
399                 printf("%d [%08lx] - %d -> %08lx ",
400                                 i, (unsigned int)bsp, j, (unsigned int)p);
401                 printf("(read %d instead of %d)\n", (int)*p, r - j);
402             }
403         }
404     }
405
406     return failed;
407 }
408 #endif