|
|
1.1 ! root 1: /* Copyright (c) 1980 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)pccaseop.c 1.12 6/10/83"; ! 4: ! 5: #include "whoami.h" ! 6: #ifdef PC ! 7: /* ! 8: * and the rest of the file ! 9: */ ! 10: #include "0.h" ! 11: #include "tree.h" ! 12: #include "objfmt.h" ! 13: #include "pcops.h" ! 14: #include "pc.h" ! 15: #include "tmps.h" ! 16: ! 17: /* ! 18: * structure for a case: ! 19: * its constant label, line number (for errors), and location label. ! 20: */ ! 21: struct ct { ! 22: long cconst; ! 23: int cline; ! 24: int clabel; ! 25: }; ! 26: ! 27: /* ! 28: * the P2FORCE operator puts its operand into a register. ! 29: * these to keep from thinking of it as r0 all over. ! 30: */ ! 31: #ifdef vax ! 32: # define FORCENAME "r0" ! 33: #endif vax ! 34: #ifdef mc68000 ! 35: # define FORCENAME "d0" ! 36: # define ADDRTEMP "a0" ! 37: #endif mc68000 ! 38: ! 39: /* ! 40: * given a tree for a case statement, generate code for it. ! 41: * this computes the expression into a register, ! 42: * puts down the code for each of the cases, ! 43: * and then decides how to do the case switching. ! 44: * tcase [0] T_CASE ! 45: * [1] lineof "case" ! 46: * [2] expression ! 47: * [3] list of cased statements: ! 48: * cstat [0] T_CSTAT ! 49: * [1] lineof ":" ! 50: * [2] list of constant labels ! 51: * [3] statement ! 52: */ ! 53: pccaseop( tcase ) ! 54: int *tcase; ! 55: { ! 56: struct nl *exprtype; ! 57: struct nl *exprnlp; ! 58: struct nl *rangetype; ! 59: long low; ! 60: long high; ! 61: long exprctype; ! 62: long swlabel; ! 63: long endlabel; ! 64: long label; ! 65: long count; ! 66: long *cstatlp; ! 67: long *cstatp; ! 68: long *casep; ! 69: struct ct *ctab; ! 70: struct ct *ctp; ! 71: long i; ! 72: long nr; ! 73: long goc; ! 74: int casecmp(); ! 75: bool dupcases; ! 76: ! 77: goc = gocnt; ! 78: /* ! 79: * find out the type of the case expression ! 80: * even if the expression has errors (exprtype == NIL), continue. ! 81: */ ! 82: line = tcase[1]; ! 83: codeoff(); ! 84: exprtype = rvalue( (int *) tcase[2] , NIL , RREQ ); ! 85: codeon(); ! 86: if ( exprtype != NIL ) { ! 87: if ( isnta( exprtype , "bcsi" ) ) { ! 88: error("Case selectors cannot be %ss" , nameof( exprtype ) ); ! 89: exprtype = NIL; ! 90: } else { ! 91: if ( exprtype -> class != RANGE ) { ! 92: rangetype = exprtype -> type; ! 93: } else { ! 94: rangetype = exprtype; ! 95: } ! 96: if ( rangetype == NIL ) { ! 97: exprtype = NIL; ! 98: } else { ! 99: low = rangetype -> range[0]; ! 100: high = rangetype -> range[1]; ! 101: } ! 102: } ! 103: } ! 104: if ( exprtype != NIL ) { ! 105: /* ! 106: * compute and save the case expression. ! 107: * also, put expression into a register ! 108: * save its c-type and jump to the code to do the switch. ! 109: */ ! 110: exprctype = p2type( exprtype ); ! 111: exprnlp = tmpalloc( sizeof (long) , nl + T4INT , NOREG ); ! 112: putRV( 0 , cbn , exprnlp -> value[ NL_OFFS ] , ! 113: exprnlp -> extra_flags , P2INT ); ! 114: (void) rvalue( (int *) tcase[2] , NIL , RREQ ); ! 115: sconv(exprctype, P2INT); ! 116: putop( P2ASSIGN , P2INT ); ! 117: putop( P2FORCE , P2INT ); ! 118: putdot( filename , line ); ! 119: swlabel = getlab(); ! 120: putjbr( swlabel ); ! 121: } ! 122: /* ! 123: * count the number of cases ! 124: * and allocate table for cases, lines, and labels ! 125: * default case goes in ctab[0]. ! 126: */ ! 127: count = 1; ! 128: for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) { ! 129: cstatp = cstatlp[1]; ! 130: if ( cstatp == NIL ) { ! 131: continue; ! 132: } ! 133: for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) { ! 134: count++; ! 135: } ! 136: } ! 137: /* ! 138: */ ! 139: ctab = (struct ct *) malloc( count * sizeof( struct ct ) ); ! 140: if ( ctab == (struct ct *) 0 ) { ! 141: error("Ran out of memory (case)"); ! 142: pexit( DIED ); ! 143: } ! 144: /* ! 145: * pick up default label and label for after case statement. ! 146: */ ! 147: ctab[0].clabel = getlab(); ! 148: endlabel = getlab(); ! 149: /* ! 150: * generate code for each case ! 151: * filling in ctab for each. ! 152: * nr is for error if no case falls out bottom. ! 153: */ ! 154: nr = 1; ! 155: count = 0; ! 156: for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) { ! 157: cstatp = cstatlp[1]; ! 158: if ( cstatp == NIL ) { ! 159: continue; ! 160: } ! 161: line = cstatp[1]; ! 162: label = getlab(); ! 163: for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) { ! 164: gconst( casep[1] ); ! 165: if( exprtype == NIL || con.ctype == NIL ) { ! 166: continue; ! 167: } ! 168: if ( incompat( con.ctype , exprtype , NIL ) ) { ! 169: cerror("Case label type clashed with case selector expression type"); ! 170: continue; ! 171: } ! 172: if ( con.crval < low || con.crval > high ) { ! 173: error("Case label out of range"); ! 174: continue; ! 175: } ! 176: count++; ! 177: ctab[ count ].cconst = con.crval; ! 178: ctab[ count ].cline = line; ! 179: ctab[ count ].clabel = label; ! 180: } ! 181: /* ! 182: * put out the statement ! 183: */ ! 184: putlab( label ); ! 185: putcnt(); ! 186: level++; ! 187: statement( cstatp[3] ); ! 188: nr = (nr && noreach); ! 189: noreach = 0; ! 190: level--; ! 191: if (gotos[cbn]) { ! 192: ungoto(); ! 193: } ! 194: putjbr( endlabel ); ! 195: } ! 196: noreach = nr; ! 197: /* ! 198: * default action is to call error ! 199: */ ! 200: putlab( ctab[0].clabel ); ! 201: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CASERNG" ); ! 202: putRV( 0 , cbn , exprnlp -> value[ NL_OFFS ] , ! 203: exprnlp -> extra_flags , P2INT ); ! 204: putop( P2CALL , P2INT ); ! 205: putdot( filename , line ); ! 206: /* ! 207: * sort the cases ! 208: */ ! 209: qsort( &ctab[1] , count , sizeof (struct ct) , casecmp ); ! 210: /* ! 211: * check for duplicates ! 212: */ ! 213: dupcases = FALSE; ! 214: for ( ctp = &ctab[1] ; ctp < &ctab[ count ] ; ctp++ ) { ! 215: if ( ctp[0].cconst == ctp[1].cconst ) { ! 216: error("Multiply defined label in case, lines %d and %d" , ! 217: ctp[0].cline , ctp[1].cline ); ! 218: dupcases = TRUE; ! 219: } ! 220: } ! 221: if ( dupcases ) { ! 222: return; ! 223: } ! 224: /* ! 225: * choose a switch algorithm and implement it: ! 226: * direct switch >= 1/3 full and >= 4 cases. ! 227: * binary switch not direct switch and > 8 cases. ! 228: * ifthenelse not direct or binary switch. ! 229: */ ! 230: putlab( swlabel ); ! 231: if ( ctab[ count ].cconst - ctab[1].cconst < 3 * count && count >= 4 ) { ! 232: directsw( ctab , count ); ! 233: } else if ( count > 8 ) { ! 234: binarysw( ctab , count ); ! 235: } else { ! 236: itesw( ctab , count ); ! 237: } ! 238: putlab( endlabel ); ! 239: if ( goc != gocnt ) { ! 240: putcnt(); ! 241: } ! 242: } ! 243: ! 244: /* ! 245: * direct switch ! 246: */ ! 247: directsw( ctab , count ) ! 248: struct ct *ctab; ! 249: int count; ! 250: { ! 251: int fromlabel = getlab(); ! 252: long i; ! 253: long j; ! 254: ! 255: # ifdef vax ! 256: if (opt('J')) { ! 257: /* ! 258: * We have a table of absolute addresses. ! 259: * ! 260: * subl2 to make r0 a 0-origin byte offset. ! 261: * cmpl check against upper limit. ! 262: * blssu error if out of bounds. ! 263: * ashl to make r0 a 0-origin long offset, ! 264: * jmp and indirect through it. ! 265: */ ! 266: putprintf(" subl2 $%d,%s", 0, ctab[1].cconst, FORCENAME); ! 267: putprintf(" cmpl $%d,%s", 0, ! 268: ctab[count].cconst - ctab[1].cconst, FORCENAME); ! 269: putprintf(" blssu %s%d", 0, LABELPREFIX, ctab[0].clabel); ! 270: putprintf(" ashl $2,%s,%s", 0, FORCENAME, FORCENAME); ! 271: putprintf(" jmp *%s%d(%s)", 0, ! 272: LABELPREFIX, fromlabel, FORCENAME); ! 273: } else { ! 274: /* ! 275: * We can use the VAX casel instruction with a table ! 276: * of short relative offsets. ! 277: */ ! 278: putprintf(" casel %s,$%d,$%d" , 0 , FORCENAME , ! 279: ctab[1].cconst , ctab[ count ].cconst - ctab[1].cconst ); ! 280: } ! 281: # endif vax ! 282: # ifdef mc68000 ! 283: /* ! 284: * subl to make d0 a 0-origin byte offset. ! 285: * cmpl check against upper limit. ! 286: * bhi error if out of bounds. ! 287: */ ! 288: putprintf(" subl #%d,%s", 0, ctab[1].cconst, FORCENAME); ! 289: putprintf(" cmpl #%d,%s", 0, ! 290: ctab[count].cconst - ctab[1].cconst, FORCENAME); ! 291: putprintf(" bhi %s%d", 0, LABELPREFIX, ctab[0].clabel); ! 292: if (opt('J')) { ! 293: /* ! 294: * We have a table of absolute addresses. ! 295: * ! 296: * asll to make d0 a 0-origin long offset. ! 297: * movl pick up a jump-table entry ! 298: * jmp and indirect through it. ! 299: */ ! 300: putprintf(" asll #2,%s", 0, FORCENAME, FORCENAME); ! 301: putprintf(" movl pc@(4,%s:l),%s", 0, FORCENAME, ADDRTEMP); ! 302: putprintf(" jmp %s@", 0, ADDRTEMP); ! 303: } else { ! 304: /* ! 305: * We have a table of relative addresses. ! 306: * ! 307: * addw to make d0 a 0-origin word offset. ! 308: * movw pick up a jump-table entry ! 309: * jmp and indirect through it. ! 310: */ ! 311: putprintf(" addw %s,%s", 0, FORCENAME, FORCENAME); ! 312: putprintf(" movw pc@(6,%s:w),%s", 0, FORCENAME, FORCENAME); ! 313: putprintf(" jmp pc@(2,%s:w)", 0, FORCENAME); ! 314: } ! 315: # endif mc68000 ! 316: putlab( fromlabel ); ! 317: i = 1; ! 318: j = ctab[1].cconst; ! 319: while ( i <= count ) { ! 320: if ( j == ctab[ i ].cconst ) { ! 321: if (opt('J')) { ! 322: putprintf( " .long " , 1 ); ! 323: putprintf( PREFIXFORMAT , 0 , LABELPREFIX , ctab[ i ].clabel ); ! 324: } else { ! 325: putprintf( " .word " , 1 ); ! 326: putprintf( PREFIXFORMAT , 1 , LABELPREFIX , ctab[ i ].clabel ); ! 327: putprintf( "-" , 1 ); ! 328: putprintf( PREFIXFORMAT , 0 , LABELPREFIX , fromlabel ); ! 329: } ! 330: i++; ! 331: } else { ! 332: if (opt('J')) { ! 333: putprintf( " .long " , 1 ); ! 334: putprintf( PREFIXFORMAT , 0 , LABELPREFIX , ctab[ 0 ].clabel ); ! 335: } else { ! 336: putprintf( " .word " , 1 ); ! 337: putprintf( PREFIXFORMAT , 1 , LABELPREFIX , ctab[ 0 ].clabel ); ! 338: putprintf( "-" , 1 ); ! 339: putprintf( PREFIXFORMAT , 0 , LABELPREFIX , fromlabel ); ! 340: } ! 341: } ! 342: j++; ! 343: } ! 344: # ifdef vax ! 345: /* ! 346: * execution continues here if value not in range of case. ! 347: */ ! 348: if (!opt('J')) ! 349: putjbr( ctab[0].clabel ); ! 350: # endif vax ! 351: } ! 352: ! 353: /* ! 354: * binary switch ! 355: * special case out default label and start recursion. ! 356: */ ! 357: binarysw( ctab , count ) ! 358: struct ct *ctab; ! 359: int count; ! 360: { ! 361: ! 362: bsrecur( ctab[0].clabel , &ctab[0] , count ); ! 363: } ! 364: ! 365: /* ! 366: * recursive log( count ) search. ! 367: */ ! 368: bsrecur( deflabel , ctab , count ) ! 369: int deflabel; ! 370: struct ct *ctab; ! 371: int count; ! 372: { ! 373: ! 374: if ( count <= 0 ) { ! 375: putjbr(deflabel); ! 376: return; ! 377: } else if ( count == 1 ) { ! 378: # ifdef vax ! 379: putprintf(" cmpl %s,$%d", 0, FORCENAME, ctab[1].cconst); ! 380: putprintf(" jeql %s%d", 0, LABELPREFIX, ctab[1].clabel); ! 381: putjbr(deflabel); ! 382: # endif vax ! 383: # ifdef mc68000 ! 384: putprintf(" cmpl #%d,%s", 0, ctab[1].cconst, FORCENAME); ! 385: putprintf(" jeq L%d", 0, LABELPREFIX, ctab[1].clabel); ! 386: putjbr(deflabel); ! 387: # endif mc68000 ! 388: return; ! 389: } else { ! 390: int half = ( count + 1 ) / 2; ! 391: int gtrlabel = getlab(); ! 392: ! 393: # ifdef vax ! 394: putprintf(" cmpl %s,$%d", 0, FORCENAME, ctab[half].cconst); ! 395: putprintf(" jgtr %s%d", 0, LABELPREFIX, gtrlabel); ! 396: putprintf(" jeql %s%d", 0, LABELPREFIX, ctab[half].clabel); ! 397: # endif vax ! 398: # ifdef mc68000 ! 399: putprintf(" cmpl #%d,%s", 0, ctab[half].cconst, FORCENAME); ! 400: putprintf(" jgt %s%d", 0, LABELPREFIX, gtrlabel); ! 401: putprintf(" jeq %s%d", 0, LABELPREFIX, ctab[half].clabel); ! 402: # endif mc68000 ! 403: bsrecur( deflabel , &ctab[0] , half - 1 ); ! 404: putlab(gtrlabel); ! 405: bsrecur( deflabel , &ctab[ half ] , count - half ); ! 406: return; ! 407: } ! 408: } ! 409: ! 410: itesw( ctab , count ) ! 411: struct ct *ctab; ! 412: int count; ! 413: { ! 414: int i; ! 415: ! 416: for ( i = 1 ; i <= count ; i++ ) { ! 417: # ifdef vax ! 418: putprintf(" cmpl %s,$%d", 0, FORCENAME, ctab[i].cconst); ! 419: putprintf(" jeql %s%d", 0, LABELPREFIX, ctab[i].clabel); ! 420: # endif vax ! 421: # ifdef mc68000 ! 422: putprintf(" cmpl #%d,%s", 0, ctab[i].cconst, FORCENAME); ! 423: putprintf(" jeq %s%d", 0, LABELPREFIX, ctab[i].clabel); ! 424: # endif mc68000 ! 425: } ! 426: putjbr(ctab[0].clabel); ! 427: return; ! 428: } ! 429: int ! 430: casecmp( this , that ) ! 431: struct ct *this; ! 432: struct ct *that; ! 433: { ! 434: if ( this -> cconst < that -> cconst ) { ! 435: return -1; ! 436: } else if ( this -> cconst > that -> cconst ) { ! 437: return 1; ! 438: } else { ! 439: return 0; ! 440: } ! 441: } ! 442: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.