1115013Smarcel/* 2160157SmarcelCopyright (c) 2003-2006 Hewlett-Packard Development Company, L.P. 3121642SmarcelPermission is hereby granted, free of charge, to any person 4121642Smarcelobtaining a copy of this software and associated documentation 5121642Smarcelfiles (the "Software"), to deal in the Software without 6121642Smarcelrestriction, including without limitation the rights to use, 7121642Smarcelcopy, modify, merge, publish, distribute, sublicense, and/or sell 8121642Smarcelcopies of the Software, and to permit persons to whom the 9121642SmarcelSoftware is furnished to do so, subject to the following 10121642Smarcelconditions: 11115013Smarcel 12121642SmarcelThe above copyright notice and this permission notice shall be 13121642Smarcelincluded in all copies or substantial portions of the Software. 14121642Smarcel 15121642SmarcelTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16121642SmarcelEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17121642SmarcelOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18121642SmarcelNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19121642SmarcelHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20121642SmarcelWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21121642SmarcelFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22121642SmarcelOTHER DEALINGS IN THE SOFTWARE. 23121642Smarcel*/ 24121642Smarcel 25160163Smarcel#ifndef _KERNEL 26115013Smarcel#include <stdlib.h> 27160163Smarcel#endif 28115013Smarcel 29115013Smarcel#include "uwx_env.h" 30115013Smarcel#include "uwx_scoreboard.h" 31115013Smarcel#include "uwx_trace.h" 32115013Smarcel 33160163Smarcel#ifdef _KERNEL 34160163Smarcelstatic unsigned short uwx_allocated; 35160163Smarcelstatic struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3]; 36115013Smarcel 37160163Smarcelstatic void 38160163Smarcelfree(struct uwx_scoreboard *p) 39160163Smarcel{ 40160163Smarcel int idx = p - uwx_scoreboard; 41160163Smarcel uwx_allocated &= ~(1 << idx); 42160163Smarcel} 43160163Smarcel 44160163Smarcelstatic struct uwx_scoreboard * 45160163Smarcelmalloc(size_t sz) 46160163Smarcel{ 47160163Smarcel int idx; 48160163Smarcel if (sz != sizeof(struct uwx_scoreboard)) 49160163Smarcel return (NULL); 50160163Smarcel for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) { 51160163Smarcel if ((uwx_allocated & (1 << idx)) == 0) { 52160163Smarcel uwx_allocated |= 1 << idx; 53160163Smarcel return (uwx_scoreboard + idx); 54160163Smarcel } 55160163Smarcel } 56160163Smarcel return (NULL); 57160163Smarcel} 58160163Smarcel#endif 59160163Smarcel 60160163Smarcel 61160157Smarcelvoid uwx_prealloc_scoreboard(struct uwx_env *env, struct uwx_scoreboard *sb) 62129059Smarcel{ 63160157Smarcel sb->id = env->nscoreboards++; 64160157Smarcel sb->nextused = env->used_scoreboards; 65160157Smarcel sb->prealloc = 1; 66160157Smarcel env->used_scoreboards = sb; 67160157Smarcel TRACE_B_PREALLOC(sb->id) 68129059Smarcel} 69129059Smarcel 70115013Smarcelstruct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env) 71115013Smarcel{ 72115013Smarcel struct uwx_scoreboard *sb; 73115013Smarcel int i; 74115013Smarcel 75115013Smarcel if (env->free_scoreboards != 0) { 76115013Smarcel sb = env->free_scoreboards; 77115013Smarcel env->free_scoreboards = sb->nextfree; 78115013Smarcel TRACE_B_REUSE(sb->id) 79115013Smarcel } 80115013Smarcel else { 81115013Smarcel if (env->allocate_cb == 0) 82115013Smarcel sb = (struct uwx_scoreboard *) 83115013Smarcel malloc(sizeof(struct uwx_scoreboard)); 84115013Smarcel else 85115013Smarcel sb = (struct uwx_scoreboard *) 86115013Smarcel (*env->allocate_cb)(sizeof(struct uwx_scoreboard)); 87115013Smarcel if (sb == 0) 88115013Smarcel return 0; 89115013Smarcel sb->id = env->nscoreboards++; 90115013Smarcel sb->nextused = env->used_scoreboards; 91160157Smarcel sb->prealloc = 0; 92115013Smarcel env->used_scoreboards = sb; 93115013Smarcel TRACE_B_ALLOC(sb->id) 94115013Smarcel } 95115013Smarcel 96115013Smarcel sb->nextstack = 0; 97115013Smarcel sb->nextlabel = 0; 98115013Smarcel for (i = 0; i < env->nsbreg; i++) 99115013Smarcel sb->rstate[i] = UWX_DISP_NONE; 100115013Smarcel sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0)); 101115013Smarcel sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0); 102120925Smarcel sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_AR_PFS); 103120925Smarcel sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_AR_UNAT); 104115013Smarcel sb->label = 0; 105115013Smarcel return sb; 106115013Smarcel} 107115013Smarcel 108160163Smarcelstatic 109115013Smarcelvoid uwx_reclaim_scoreboards(struct uwx_env *env) 110115013Smarcel{ 111115013Smarcel struct uwx_scoreboard *sb; 112115013Smarcel 113115013Smarcel env->free_scoreboards = 0; 114115013Smarcel for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) { 115115013Smarcel sb->nextfree = env->free_scoreboards; 116115013Smarcel env->free_scoreboards = sb; 117115013Smarcel } 118115013Smarcel env->labeled_scoreboards = 0; 119115013Smarcel} 120115013Smarcel 121115013Smarcelstruct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env) 122115013Smarcel{ 123115013Smarcel struct uwx_scoreboard *sb; 124115013Smarcel 125115013Smarcel uwx_reclaim_scoreboards(env); 126115013Smarcel sb = uwx_alloc_scoreboard(env); 127115013Smarcel return sb; 128115013Smarcel} 129115013Smarcel 130115013Smarcelstruct uwx_scoreboard *uwx_new_scoreboard( 131115013Smarcel struct uwx_env *env, 132115013Smarcel struct uwx_scoreboard *prevsb) 133115013Smarcel{ 134115013Smarcel int i; 135115013Smarcel struct uwx_scoreboard *sb; 136115013Smarcel 137115013Smarcel sb = uwx_alloc_scoreboard(env); 138115013Smarcel if (sb == 0) 139115013Smarcel return 0; 140115013Smarcel sb->nextstack = prevsb; 141115013Smarcel for (i = 0; i < env->nsbreg; i++) 142115013Smarcel sb->rstate[i] = prevsb->rstate[i]; 143115013Smarcel return sb; 144115013Smarcel} 145115013Smarcel 146115013Smarcelstruct uwx_scoreboard *uwx_pop_scoreboards( 147115013Smarcel struct uwx_env *env, 148115013Smarcel struct uwx_scoreboard *sb, 149115013Smarcel int ecount) 150115013Smarcel{ 151115013Smarcel struct uwx_scoreboard *next; 152115013Smarcel 153115013Smarcel while (ecount > 0) { 154115013Smarcel next = sb->nextstack; 155115013Smarcel TRACE_B_POP(sb->id) 156115013Smarcel sb->nextstack = 0; 157115013Smarcel sb->nextfree = env->free_scoreboards; 158115013Smarcel env->free_scoreboards = sb; 159115013Smarcel sb = next; 160115013Smarcel if (sb == 0) 161115013Smarcel return 0; 162115013Smarcel ecount--; 163115013Smarcel } 164115013Smarcel return sb; 165115013Smarcel} 166115013Smarcel 167115013Smarcelint uwx_label_scoreboard( 168115013Smarcel struct uwx_env *env, 169115013Smarcel struct uwx_scoreboard *sb, 170115013Smarcel int label) 171115013Smarcel{ 172115013Smarcel struct uwx_scoreboard *new; 173115013Smarcel struct uwx_scoreboard *back; 174115013Smarcel struct uwx_scoreboard *next; 175115013Smarcel int i; 176115013Smarcel 177115013Smarcel TRACE_B_LABEL(label) 178115013Smarcel 179115013Smarcel /* Copy the current stack, storing reverse links */ 180115013Smarcel /* in the "nextstack" field. */ 181115013Smarcel 182115013Smarcel back = 0; 183160163Smarcel new = 0; 184115013Smarcel while (sb != 0) { 185115013Smarcel TRACE_B_LABEL_COPY(sb->id) 186115013Smarcel new = uwx_alloc_scoreboard(env); 187115013Smarcel if (new == 0) 188115013Smarcel return UWX_ERR_NOMEM; 189115013Smarcel new->nextstack = back; 190115013Smarcel for (i = 0; i < env->nsbreg; i++) 191115013Smarcel new->rstate[i] = sb->rstate[i]; 192115013Smarcel sb = sb->nextstack; 193115013Smarcel back = new; 194115013Smarcel } 195115013Smarcel 196115013Smarcel /* The "new" pointer now points to the bottom of the new stack, */ 197115013Smarcel /* and the "nextstack" links lead towards the top. */ 198115013Smarcel /* Now go back down the stack, reversing the stack links to their */ 199115013Smarcel /* proper direction. */ 200115013Smarcel 201115013Smarcel back = 0; 202115013Smarcel while (new != 0) { 203115013Smarcel next = new->nextstack; 204115013Smarcel new->nextstack = back; 205115013Smarcel TRACE_B_LABEL_REVERSE(back, new) 206115013Smarcel back = new; 207115013Smarcel new = next; 208115013Smarcel } 209115013Smarcel 210115013Smarcel /* The "back" pointer now points to the top of the stack. */ 211115013Smarcel 212115013Smarcel back->label = label; 213115013Smarcel back->nextlabel = env->labeled_scoreboards; 214115013Smarcel env->labeled_scoreboards = back; 215115013Smarcel return UWX_OK; 216115013Smarcel} 217115013Smarcel 218115013Smarcelint uwx_copy_scoreboard( 219115013Smarcel struct uwx_env *env, 220115013Smarcel struct uwx_scoreboard *sb, 221115013Smarcel int label) 222115013Smarcel{ 223115013Smarcel struct uwx_scoreboard *next; 224115013Smarcel struct uwx_scoreboard *next2; 225115013Smarcel struct uwx_scoreboard *lsb; 226115013Smarcel struct uwx_scoreboard *new; 227115013Smarcel struct uwx_scoreboard *back; 228115013Smarcel int i; 229115013Smarcel 230115013Smarcel TRACE_B_COPY(label, sb->id) 231115013Smarcel 232115013Smarcel /* Free the existing stack. */ 233115013Smarcel 234115013Smarcel next = sb->nextstack; 235115013Smarcel while (next != 0) { 236115013Smarcel TRACE_B_COPY_FREE(next->id) 237115013Smarcel next2 = next->nextstack; 238115013Smarcel next->nextstack = 0; 239115013Smarcel next->nextfree = env->free_scoreboards; 240115013Smarcel env->free_scoreboards = next; 241115013Smarcel next = next2; 242115013Smarcel } 243115013Smarcel 244115013Smarcel /* Find the scoreboard with the requested label. */ 245115013Smarcel 246115013Smarcel for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) { 247115013Smarcel if (lsb->label == label) 248115013Smarcel break; 249115013Smarcel } 250115013Smarcel 251115013Smarcel if (lsb == 0) 252115013Smarcel return UWX_ERR_UNDEFLABEL; 253115013Smarcel 254115013Smarcel TRACE_B_COPY_FOUND(lsb->id) 255115013Smarcel 256115013Smarcel /* Copy the labeled scoreboard. */ 257115013Smarcel 258115013Smarcel sb->nextstack = 0; 259115013Smarcel sb->nextlabel = 0; 260115013Smarcel for (i = 0; i < env->nsbreg; i++) 261115013Smarcel sb->rstate[i] = lsb->rstate[i]; 262115013Smarcel sb->label = 0; 263115013Smarcel 264115013Smarcel /* Now copy its stack, storing reverse links in the nextstack field. */ 265115013Smarcel 266115013Smarcel back = sb; 267160163Smarcel new = 0; 268115013Smarcel for (next = lsb->nextstack; next != 0; next = next->nextstack) { 269115013Smarcel TRACE_B_COPY_COPY(next->id) 270115013Smarcel new = uwx_alloc_scoreboard(env); 271115013Smarcel if (new == 0) 272115013Smarcel return UWX_ERR_NOMEM; 273115013Smarcel new->nextstack = back; 274115013Smarcel for (i = 0; i < env->nsbreg; i++) 275115013Smarcel new->rstate[i] = next->rstate[i]; 276115013Smarcel back = new; 277115013Smarcel } 278115013Smarcel 279115013Smarcel /* The "new" pointer now points to the bottom of the new stack, */ 280115013Smarcel /* and the "nextstack" links lead towards the top. */ 281115013Smarcel /* Now go back down the stack, reversing the nextstack links to their */ 282115013Smarcel /* proper direction. */ 283115013Smarcel 284115013Smarcel back = 0; 285115013Smarcel while (new != 0) { 286115013Smarcel next = new->nextstack; 287115013Smarcel new->nextstack = back; 288115013Smarcel TRACE_B_COPY_REVERSE(back, new) 289115013Smarcel back = new; 290115013Smarcel new = next; 291115013Smarcel } 292115013Smarcel 293115013Smarcel return UWX_OK; 294115013Smarcel} 295115013Smarcel 296115013Smarcelvoid uwx_free_scoreboards(struct uwx_env *env) 297115013Smarcel{ 298115013Smarcel struct uwx_scoreboard *sb; 299115013Smarcel struct uwx_scoreboard *next; 300115013Smarcel 301115013Smarcel for (sb = env->used_scoreboards; sb != 0; sb = next) { 302115013Smarcel TRACE_B_FREE(sb->id) 303115013Smarcel next = sb->nextused; 304160157Smarcel if (!sb->prealloc) { 305160157Smarcel if (env->free_cb == 0) 306160157Smarcel free((void *)sb); 307160157Smarcel else 308160157Smarcel (*env->free_cb)((void *)sb); 309160157Smarcel } 310115013Smarcel } 311115013Smarcel env->free_scoreboards = 0; 312115013Smarcel env->used_scoreboards = 0; 313115013Smarcel env->labeled_scoreboards = 0; 314115013Smarcel} 315115013Smarcel 316