uwx_scoreboard.c revision 160157
1/*
2Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3Permission is hereby granted, free of charge, to any person
4obtaining a copy of this software and associated documentation
5files (the "Software"), to deal in the Software without
6restriction, including without limitation the rights to use,
7copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following
10conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23*/
24
25#include <stdlib.h>
26
27#include "uwx_env.h"
28#include "uwx_scoreboard.h"
29#include "uwx_trace.h"
30
31
32void uwx_prealloc_scoreboard(struct uwx_env *env, struct uwx_scoreboard *sb)
33{
34    sb->id = env->nscoreboards++;
35    sb->nextused = env->used_scoreboards;
36    sb->prealloc = 1;
37    env->used_scoreboards = sb;
38    TRACE_B_PREALLOC(sb->id)
39}
40
41struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
42{
43    struct uwx_scoreboard *sb;
44    int i;
45
46    if (env->free_scoreboards != 0) {
47	sb = env->free_scoreboards;
48	env->free_scoreboards = sb->nextfree;
49	TRACE_B_REUSE(sb->id)
50    }
51    else {
52	if (env->allocate_cb == 0)
53	    sb = (struct uwx_scoreboard *)
54			malloc(sizeof(struct uwx_scoreboard));
55	else
56	    sb = (struct uwx_scoreboard *)
57			(*env->allocate_cb)(sizeof(struct uwx_scoreboard));
58	if (sb == 0)
59	    return 0;
60	sb->id = env->nscoreboards++;
61	sb->nextused = env->used_scoreboards;
62	sb->prealloc = 0;
63	env->used_scoreboards = sb;
64	TRACE_B_ALLOC(sb->id)
65    }
66
67    sb->nextstack = 0;
68    sb->nextlabel = 0;
69    for (i = 0; i < env->nsbreg; i++)
70	sb->rstate[i] = UWX_DISP_NONE;
71    sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0));
72    sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
73    sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_AR_PFS);
74    sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_AR_UNAT);
75    sb->label = 0;
76    return sb;
77}
78
79void uwx_reclaim_scoreboards(struct uwx_env *env)
80{
81    struct uwx_scoreboard *sb;
82
83    env->free_scoreboards = 0;
84    for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) {
85	sb->nextfree = env->free_scoreboards;
86	env->free_scoreboards = sb;
87    }
88    env->labeled_scoreboards = 0;
89}
90
91struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env)
92{
93    struct uwx_scoreboard *sb;
94
95    uwx_reclaim_scoreboards(env);
96    sb = uwx_alloc_scoreboard(env);
97    return sb;
98}
99
100struct uwx_scoreboard *uwx_new_scoreboard(
101    struct uwx_env *env,
102    struct uwx_scoreboard *prevsb)
103{
104    int i;
105    struct uwx_scoreboard *sb;
106
107    sb = uwx_alloc_scoreboard(env);
108    if (sb == 0)
109	return 0;
110    sb->nextstack = prevsb;
111    for (i = 0; i < env->nsbreg; i++)
112	sb->rstate[i] = prevsb->rstate[i];
113    return sb;
114}
115
116struct uwx_scoreboard *uwx_pop_scoreboards(
117    struct uwx_env *env,
118    struct uwx_scoreboard *sb,
119    int ecount)
120{
121    struct uwx_scoreboard *next;
122
123    while (ecount > 0) {
124	next = sb->nextstack;
125	TRACE_B_POP(sb->id)
126	sb->nextstack = 0;
127	sb->nextfree = env->free_scoreboards;
128	env->free_scoreboards = sb;
129	sb = next;
130	if (sb == 0)
131	    return 0;
132	ecount--;
133    }
134    return sb;
135}
136
137int uwx_label_scoreboard(
138    struct uwx_env *env,
139    struct uwx_scoreboard *sb,
140    int label)
141{
142    struct uwx_scoreboard *new;
143    struct uwx_scoreboard *back;
144    struct uwx_scoreboard *next;
145    int i;
146
147    TRACE_B_LABEL(label)
148
149    /* Copy the current stack, storing reverse links */
150    /* in the "nextstack" field. */
151
152    back = 0;
153    while (sb != 0) {
154	TRACE_B_LABEL_COPY(sb->id)
155	new = uwx_alloc_scoreboard(env);
156	if (new == 0)
157	    return UWX_ERR_NOMEM;
158	new->nextstack = back;
159	for (i = 0; i < env->nsbreg; i++)
160	    new->rstate[i] = sb->rstate[i];
161	sb = sb->nextstack;
162	back = new;
163    }
164
165    /* The "new" pointer now points to the bottom of the new stack, */
166    /* and the "nextstack" links lead towards the top. */
167    /* Now go back down the stack, reversing the stack links to their */
168    /* proper direction. */
169
170    back = 0;
171    while (new != 0) {
172	next = new->nextstack;
173	new->nextstack = back;
174	TRACE_B_LABEL_REVERSE(back, new)
175	back = new;
176	new = next;
177    }
178
179    /* The "back" pointer now points to the top of the stack. */
180
181    back->label = label;
182    back->nextlabel = env->labeled_scoreboards;
183    env->labeled_scoreboards = back;
184    return UWX_OK;
185}
186
187int uwx_copy_scoreboard(
188    struct uwx_env *env,
189    struct uwx_scoreboard *sb,
190    int label)
191{
192    struct uwx_scoreboard *next;
193    struct uwx_scoreboard *next2;
194    struct uwx_scoreboard *lsb;
195    struct uwx_scoreboard *new;
196    struct uwx_scoreboard *back;
197    int i;
198
199    TRACE_B_COPY(label, sb->id)
200
201    /* Free the existing stack. */
202
203    next = sb->nextstack;
204    while (next != 0) {
205	TRACE_B_COPY_FREE(next->id)
206	next2 = next->nextstack;
207	next->nextstack = 0;
208	next->nextfree = env->free_scoreboards;
209	env->free_scoreboards = next;
210	next = next2;
211    }
212
213    /* Find the scoreboard with the requested label. */
214
215    for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) {
216	if (lsb->label == label)
217	    break;
218    }
219
220    if (lsb == 0)
221	return UWX_ERR_UNDEFLABEL;
222
223    TRACE_B_COPY_FOUND(lsb->id)
224
225    /* Copy the labeled scoreboard. */
226
227    sb->nextstack = 0;
228    sb->nextlabel = 0;
229    for (i = 0; i < env->nsbreg; i++)
230	sb->rstate[i] = lsb->rstate[i];
231    sb->label = 0;
232
233    /* Now copy its stack, storing reverse links in the nextstack field. */
234
235    back = sb;
236    for (next = lsb->nextstack; next != 0; next = next->nextstack) {
237	TRACE_B_COPY_COPY(next->id)
238	new = uwx_alloc_scoreboard(env);
239	if (new == 0)
240	    return UWX_ERR_NOMEM;
241	new->nextstack = back;
242	for (i = 0; i < env->nsbreg; i++)
243	    new->rstate[i] = next->rstate[i];
244	back = new;
245    }
246
247    /* The "new" pointer now points to the bottom of the new stack, */
248    /* and the "nextstack" links lead towards the top. */
249    /* Now go back down the stack, reversing the nextstack links to their */
250    /* proper direction. */
251
252    back = 0;
253    while (new != 0) {
254	next = new->nextstack;
255	new->nextstack = back;
256	TRACE_B_COPY_REVERSE(back, new)
257	back = new;
258	new = next;
259    }
260
261    return UWX_OK;
262}
263
264void uwx_free_scoreboards(struct uwx_env *env)
265{
266    struct uwx_scoreboard *sb;
267    struct uwx_scoreboard *next;
268
269    for (sb = env->used_scoreboards; sb != 0; sb = next) {
270	TRACE_B_FREE(sb->id)
271	next = sb->nextused;
272	if (!sb->prealloc) {
273	    if (env->free_cb == 0)
274		free((void *)sb);
275	    else
276		(*env->free_cb)((void *)sb);
277	}
278    }
279    env->free_scoreboards = 0;
280    env->used_scoreboards = 0;
281    env->labeled_scoreboards = 0;
282}
283
284