uwx_scoreboard.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#ifndef _KERNEL
24#include <stdlib.h>
25#else
26#define	free(p)		/* nullified */
27#define	malloc(sz)	NULL
28#endif
29
30#include "uwx_env.h"
31#include "uwx_scoreboard.h"
32#include "uwx_trace.h"
33
34
35struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
36{
37    struct uwx_scoreboard *sb;
38    int i;
39
40    if (env->free_scoreboards != 0) {
41	sb = env->free_scoreboards;
42	env->free_scoreboards = sb->nextfree;
43	TRACE_B_REUSE(sb->id)
44    }
45    else {
46	if (env->allocate_cb == 0)
47	    sb = (struct uwx_scoreboard *)
48			malloc(sizeof(struct uwx_scoreboard));
49	else
50	    sb = (struct uwx_scoreboard *)
51			(*env->allocate_cb)(sizeof(struct uwx_scoreboard));
52	if (sb == 0)
53	    return 0;
54	sb->id = env->nscoreboards++;
55	sb->nextused = env->used_scoreboards;
56	env->used_scoreboards = sb;
57	TRACE_B_ALLOC(sb->id)
58    }
59
60    sb->nextstack = 0;
61    sb->nextlabel = 0;
62    for (i = 0; i < env->nsbreg; i++)
63	sb->rstate[i] = UWX_DISP_NONE;
64    sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0));
65    sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
66    sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_PFS);
67    sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_UNAT);
68    sb->label = 0;
69    return sb;
70}
71
72static
73void uwx_reclaim_scoreboards(struct uwx_env *env)
74{
75    struct uwx_scoreboard *sb;
76
77    env->free_scoreboards = 0;
78    for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) {
79	sb->nextfree = env->free_scoreboards;
80	env->free_scoreboards = sb;
81    }
82    env->labeled_scoreboards = 0;
83}
84
85struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env)
86{
87    struct uwx_scoreboard *sb;
88
89    uwx_reclaim_scoreboards(env);
90    sb = uwx_alloc_scoreboard(env);
91    return sb;
92}
93
94struct uwx_scoreboard *uwx_new_scoreboard(
95    struct uwx_env *env,
96    struct uwx_scoreboard *prevsb)
97{
98    int i;
99    struct uwx_scoreboard *sb;
100
101    sb = uwx_alloc_scoreboard(env);
102    if (sb == 0)
103	return 0;
104    sb->nextstack = prevsb;
105    for (i = 0; i < env->nsbreg; i++)
106	sb->rstate[i] = prevsb->rstate[i];
107    return sb;
108}
109
110struct uwx_scoreboard *uwx_pop_scoreboards(
111    struct uwx_env *env,
112    struct uwx_scoreboard *sb,
113    int ecount)
114{
115    struct uwx_scoreboard *next;
116
117    while (ecount > 0) {
118	next = sb->nextstack;
119	TRACE_B_POP(sb->id)
120	sb->nextstack = 0;
121	sb->nextfree = env->free_scoreboards;
122	env->free_scoreboards = sb;
123	sb = next;
124	if (sb == 0)
125	    return 0;
126	ecount--;
127    }
128    return sb;
129}
130
131int uwx_label_scoreboard(
132    struct uwx_env *env,
133    struct uwx_scoreboard *sb,
134    int label)
135{
136    struct uwx_scoreboard *new;
137    struct uwx_scoreboard *back;
138    struct uwx_scoreboard *next;
139    int i;
140
141    TRACE_B_LABEL(label)
142
143    /* Copy the current stack, storing reverse links */
144    /* in the "nextstack" field. */
145
146    back = 0;
147    new = 0;
148    while (sb != 0) {
149	TRACE_B_LABEL_COPY(sb->id)
150	new = uwx_alloc_scoreboard(env);
151	if (new == 0)
152	    return UWX_ERR_NOMEM;
153	new->nextstack = back;
154	for (i = 0; i < env->nsbreg; i++)
155	    new->rstate[i] = sb->rstate[i];
156	sb = sb->nextstack;
157	back = new;
158    }
159
160    /* The "new" pointer now points to the bottom of the new stack, */
161    /* and the "nextstack" links lead towards the top. */
162    /* Now go back down the stack, reversing the stack links to their */
163    /* proper direction. */
164
165    back = 0;
166    while (new != 0) {
167	next = new->nextstack;
168	new->nextstack = back;
169	TRACE_B_LABEL_REVERSE(back, new)
170	back = new;
171	new = next;
172    }
173
174    /* The "back" pointer now points to the top of the stack. */
175
176    back->label = label;
177    back->nextlabel = env->labeled_scoreboards;
178    env->labeled_scoreboards = back;
179    return UWX_OK;
180}
181
182int uwx_copy_scoreboard(
183    struct uwx_env *env,
184    struct uwx_scoreboard *sb,
185    int label)
186{
187    struct uwx_scoreboard *next;
188    struct uwx_scoreboard *next2;
189    struct uwx_scoreboard *lsb;
190    struct uwx_scoreboard *new;
191    struct uwx_scoreboard *back;
192    int i;
193
194    TRACE_B_COPY(label, sb->id)
195
196    /* Free the existing stack. */
197
198    next = sb->nextstack;
199    while (next != 0) {
200	TRACE_B_COPY_FREE(next->id)
201	next2 = next->nextstack;
202	next->nextstack = 0;
203	next->nextfree = env->free_scoreboards;
204	env->free_scoreboards = next;
205	next = next2;
206    }
207
208    /* Find the scoreboard with the requested label. */
209
210    for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) {
211	if (lsb->label == label)
212	    break;
213    }
214
215    if (lsb == 0)
216	return UWX_ERR_UNDEFLABEL;
217
218    TRACE_B_COPY_FOUND(lsb->id)
219
220    /* Copy the labeled scoreboard. */
221
222    sb->nextstack = 0;
223    sb->nextlabel = 0;
224    for (i = 0; i < env->nsbreg; i++)
225	sb->rstate[i] = lsb->rstate[i];
226    sb->label = 0;
227
228    /* Now copy its stack, storing reverse links in the nextstack field. */
229
230    back = sb;
231    new = 0;
232    for (next = lsb->nextstack; next != 0; next = next->nextstack) {
233	TRACE_B_COPY_COPY(next->id)
234	new = uwx_alloc_scoreboard(env);
235	if (new == 0)
236	    return UWX_ERR_NOMEM;
237	new->nextstack = back;
238	for (i = 0; i < env->nsbreg; i++)
239	    new->rstate[i] = next->rstate[i];
240	back = new;
241    }
242
243    /* The "new" pointer now points to the bottom of the new stack, */
244    /* and the "nextstack" links lead towards the top. */
245    /* Now go back down the stack, reversing the nextstack links to their */
246    /* proper direction. */
247
248    back = 0;
249    while (new != 0) {
250	next = new->nextstack;
251	new->nextstack = back;
252	TRACE_B_COPY_REVERSE(back, new)
253	back = new;
254	new = next;
255    }
256
257    return UWX_OK;
258}
259
260void uwx_free_scoreboards(struct uwx_env *env)
261{
262    struct uwx_scoreboard *sb;
263    struct uwx_scoreboard *next;
264
265    for (sb = env->used_scoreboards; sb != 0; sb = next) {
266	TRACE_B_FREE(sb->id)
267	next = sb->nextused;
268	if (env->free_cb == 0)
269	    free((void *)sb);
270	else
271	    (*env->free_cb)((void *)sb);
272    }
273    env->free_scoreboards = 0;
274    env->used_scoreboards = 0;
275    env->labeled_scoreboards = 0;
276}
277
278