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