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