|
|
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.