|
|
1.1 root 1: /*
2: * functions to help pi put out
3: * polish postfix binary portable c compiler intermediate code
4: * thereby becoming the portable pascal compiler
5: */
6:
7: #include "whoami"
8: #ifdef PPC
9: #include "0.h"
10: #include "opcode.h"
11: #include "ppc.h"
12:
13: /*
14: * extract from pi's format
15: */
16: #define FROMPI( nth , word ) ( ( ( word ) >> ( (nth) * 8 ) ) & 0377 )
17:
18: /*
19: * mash into f77's format
20: */
21: #define TOF77( fop,val,rest ) ( ( ( (rest) & 0177777 ) << 16 ) \
22: | ( ( (val) & 0377 ) << 8 ) \
23: | ( (fop) & 0377 ) )
24:
25: /*
26: * this version of put generates stephen c johnson intermediate code
27: * as modified for the fortran77 compiler, to be both
28: * binary and postfix.
29: * it still uses the address of its argument
30: * as the address of its (variable length) argument list.
31: * the name is changed by a #define for the ctags program.
32: */
33: #define ppcput put
34: ppcput( arglist )
35: {
36: register int *argp;
37: int narg;
38: int op;
39: int subop;
40:
41: /*
42: * are we not generating code?
43: */
44: if ( cgenflg )
45: return;
46: argp = &arglist;
47: narg = *argp++;
48: op = FROMPI( 0 , *argp );
49: subop = FROMPI( 1 , *argp );
50: putprintf( "# [put] op = 0%o subop = %d argp[1] = %d"
51: , op , subop , argp[1] );
52: switch( op ) {
53: default:
54: /*
55: * panic( "[put] op" );
56: */
57: putprintf( "# [put] op ignored" );
58: break;
59: case O_LV:
60: putLV( subop >> 1 , argp[1] , P2PTR | P2INT );
61: break;
62: case O_RV1:
63: case O_RV2:
64: case O_RV4:
65: case O_RV8:
66: putRV( op , subop >> 1 , argp[1] , 0 );
67: break;
68: case O_RV:
69: putRV( op , subop >> 1 , argp[1] , argp[2] );
70: break;
71: case O_CON1:
72: case O_CON2:
73: case O_CON4:
74: putCON( op , argp[1] );
75: break;
76: case O_CON8:
77: putCON( op , *( (double *) &argp[1] ) );
78: break;
79: case O_AS21:
80: case O_AS41:
81: case O_AS2:
82: case O_AS42:
83: case O_AS24:
84: case O_AS4:
85: case O_AS28:
86: case O_AS48:
87: case O_AS8:
88: putAS( op , 0 );
89: break;
90: case O_AS:
91: putAS( op , argp[1] );
92: break;
93: case O_ADD2:
94: case O_ADD42:
95: case O_ADD82:
96: case O_ADD24:
97: case O_ADD4:
98: case O_ADD84:
99: case O_ADD28:
100: case O_ADD48:
101: case O_ADD8:
102: putADD( op );
103: break;
104: case O_SUB2:
105: case O_SUB42:
106: case O_SUB82:
107: case O_SUB24:
108: case O_SUB4:
109: case O_SUB84:
110: case O_SUB28:
111: case O_SUB48:
112: case O_SUB8:
113: putSUB( op );
114: break;
115: case O_MUL2:
116: case O_MUL42:
117: case O_MUL82:
118: case O_MUL24:
119: case O_MUL4:
120: case O_MUL84:
121: case O_MUL28:
122: case O_MUL48:
123: case O_MUL8:
124: putMUL( op );
125: break;
126: case O_DVD2:
127: case O_DVD42:
128: case O_DVD82:
129: case O_DVD24:
130: case O_DVD4:
131: case O_DVD84:
132: case O_DVD28:
133: case O_DVD48:
134: case O_DVD8:
135: putDVD( op );
136: break;
137: case O_DIV2:
138: case O_DIV42:
139: case O_DIV24:
140: case O_DIV4:
141: putDIV( op );
142: break;
143: case O_MOD2:
144: case O_MOD42:
145: case O_MOD24:
146: case O_MOD4:
147: putMOD( op );
148: break;
149: }
150: }
151:
152:
153: putLV( level , offset , type )
154: int level;
155: int offset;
156: int type;
157: {
158: if ( level == cbn ) {
159: putleaf( P2REG , 0 , P2FP , P2PTR | P2INT , 0 );
160: } else {
161: putleaf( P2NAME , level * sizeof (int *) , 0 , P2PTR | P2INT
162: , "_display" );
163: }
164: putleaf( P2ICON , offset , 0 , P2INT , 0 );
165: putop( P2PLUS , P2PTR | P2INT );
166: putop( P2UNARY P2MUL , type );
167: }
168:
169: /*
170: * an operand, given its level and offset,
171: * and its length if it is other than 1, 2, 4, or 8
172: */
173: putRV( op , level , offset , length )
174: int op;
175: int level;
176: int offset;
177: int length;
178: {
179: int type;
180:
181: switch ( op ) {
182: default:
183: panic( "putRV" );
184: case O_RV:
185: /*
186: * no structures, yet
187: */
188: panic( "putRV O_RV" );
189: case O_RV1:
190: type = P2CHAR;
191: break;
192: case O_RV2:
193: type = P2SHORT;
194: break;
195: case O_RV4:
196: type = P2LONG;
197: break;
198: case O_RV8:
199: type = P2DOUBLE;
200: break;
201: }
202: putLV( level , offset , type );
203: }
204:
205: putCON( op , value )
206: int op;
207: int value;
208: {
209: int type;
210:
211: switch( op ) {
212: case O_CON1:
213: type = P2CHAR;
214: break;
215: case O_CON2:
216: type = P2SHORT;
217: break;
218: case O_CON4:
219: type = P2LONG;
220: break;
221: case O_CON8:
222: type = P2DOUBLE;
223: break;
224: }
225: if ( type != P2DOUBLE ) {
226: putleaf( P2ICON , value , 0 , type , 0 );
227: } else {
228: char name[8];
229:
230: sprintf( name , "D%d" , newlabel() );
231: puttext( " .data" );
232: puttext( " .align 2" );
233: putprintf( "%s:" , name );
234: putprintf( " .double 0d%.20e" , *( (double *) &value ) );
235: puttext( " .text" );
236: puttext( " .align 1" );
237: putleaf( P2NAME , 0 , 0 , P2DOUBLE , name );
238: }
239: }
240:
241: /*
242: * generate an assignment
243: * given the length of the destination if not 1, 2, 4, or 8
244: */
245: putAS( op , length )
246: int op;
247: int length;
248: {
249: int type;
250:
251: switch ( op ) {
252: default:
253: panic( "[putAS]" );
254: case O_AS:
255: /*
256: * no structures, yet
257: */
258: panic( "[putAS] O_AS" );
259: case O_AS21:
260: case O_AS41:
261: type = P2CHAR;
262: break;
263: case O_AS2:
264: case O_AS42:
265: type = P2SHORT;
266: break;
267: case O_AS24:
268: case O_AS4:
269: type = P2LONG;
270: break;
271: case O_AS28:
272: case O_AS48:
273: case O_AS8:
274: type = P2DOUBLE;
275: break;
276: }
277: putop( P2ASSIGN , type );
278: }
279:
280: /*
281: * the various additions
282: */
283: putADD( op )
284: int op;
285: {
286: int type;
287:
288: switch ( op ) {
289: case O_ADD2:
290: case O_ADD42:
291: case O_ADD82:
292: type = P2SHORT;
293: break;
294: case O_ADD24:
295: case O_ADD4:
296: case O_ADD84:
297: type = P2LONG;
298: break;
299: case O_ADD28:
300: case O_ADD48:
301: case O_ADD8:
302: type = P2DOUBLE;
303: break;
304: }
305: putop( P2PLUS , type );
306: }
307:
308: /*
309: * the various subtractions
310: */
311: putSUB( op )
312: int op;
313: {
314: int type;
315:
316: switch ( op ) {
317: case O_SUB2:
318: case O_SUB42:
319: case O_SUB82:
320: type = P2SHORT;
321: break;
322: case O_SUB24:
323: case O_SUB4:
324: case O_SUB84:
325: type = P2LONG;
326: break;
327: case O_SUB28:
328: case O_SUB48:
329: case O_SUB8:
330: type = P2DOUBLE;
331: break;
332: }
333: putop( P2MINUS , type );
334: }
335:
336: /*
337: * the various multiplications
338: */
339: putMUL( op )
340: int op;
341: {
342: int type;
343:
344: switch ( op ) {
345: case O_MUL2:
346: case O_MUL42:
347: case O_MUL82:
348: type = P2SHORT;
349: break;
350: case O_MUL24:
351: case O_MUL4:
352: case O_MUL84:
353: type = P2LONG;
354: break;
355: case O_MUL28:
356: case O_MUL48:
357: case O_MUL8:
358: type = P2DOUBLE;
359: break;
360: }
361: putop( P2MUL , type );
362: }
363:
364: /*
365: * the various divisions (floating results)
366: */
367: putDVD( op )
368: int op;
369: {
370: int type;
371:
372: switch ( op ) {
373: case O_DVD2:
374: case O_DVD42:
375: case O_DVD82:
376: type = P2SHORT;
377: break;
378: case O_DVD24:
379: case O_DVD4:
380: case O_DVD84:
381: type = P2LONG;
382: break;
383: case O_DVD28:
384: case O_DVD48:
385: case O_DVD8:
386: type = P2DOUBLE;
387: break;
388: }
389: /*
390: * convert the right operand to a double to force floating result
391: * putop( P2SCONV , P2DOUBLE );
392: * unfortunately, this doesn't work, and both operands have to
393: * be converted, and it's too late to get the left one. (sigh).
394: * that would work if the left operand were already a double,
395: * but for now ...
396: */
397: if ( op != O_DVD8 )
398: panic( "[putDVD]" );
399: putop( P2DIV , type );
400: }
401:
402: /*
403: * the various DIVs (truncated integer results)
404: */
405: putDIV( op )
406: int op;
407: {
408: int type;
409:
410: switch ( op ) {
411: case O_DIV2:
412: case O_DIV42:
413: type = P2SHORT;
414: break;
415: case O_DIV24:
416: case O_DIV4:
417: type = P2LONG;
418: break;
419: }
420: putop( P2DIV , type );
421: }
422:
423: /*
424: * the various MODs (truncated integer results)
425: */
426: putMOD( op )
427: int op;
428: {
429: int type;
430:
431: switch ( op ) {
432: case O_MOD2:
433: case O_MOD42:
434: type = P2SHORT;
435: break;
436: case O_MOD24:
437: case O_MOD4:
438: type = P2LONG;
439: break;
440: }
441: putop( P2MOD , type );
442: }
443:
444:
445: /*
446: * this returns a unique integer to be made into a label
447: */
448: int
449: newlabel()
450: {
451: static lastlabel = 0;
452:
453: return ++lastlabel;
454: }
455:
456: /*
457: * to round string lengths up to 0 mod 4
458: */
459: str4len( string )
460: char *string;
461: {
462:
463: return ( ( strlen( string ) + 3 ) / 4 );
464: }
465:
466:
467: /*
468: * emits an ftext operator and a string to the ppcstream
469: */
470: puttext( string )
471: char *string;
472: {
473: int length = str4len( string );
474:
475: emitword( TOF77( P2FTEXT , length , 0 ) );
476: # ifdef DEBUG
477: if ( ppcdebug ) {
478: fprintf( ppcdstream , "P2FTEXT | %d | 0\n" , length );
479: }
480: # endif
481: emitstring( string );
482: }
483:
484: /*
485: * puts out formatted text to the ppcstream.
486: * none of arg1 .. arg5 need be present.
487: * and you can add more if you need them.
488: */
489: /* VARARGS */
490: putprintf( format , arg1 , arg2 , arg3 , arg4 , arg5 )
491: char *format;
492: {
493: char buffer[128];
494:
495: sprintf( buffer , format , arg1 , arg2 , arg3 , arg4 , arg5 );
496: puttext( buffer );
497: }
498:
499: /*
500: * emit a left bracket operator to ppcstream
501: * with function number, the maximum temp register, and total locals
502: * from globals ftnno and sizes[ cbn ]
503: * until i figure out how to use them, regs 0 .. 11 are free.
504: * one idea for one reg is to save the display pointer on block entry
505: */
506: putlbracket()
507: {
508: # define MAXTP2REG 11
509: # define BITSPERBYTE 8
510:
511: emitword( TOF77( P2FLBRAC , MAXTP2REG , ftnno ) );
512: emitword( BITSPERBYTE * -sizes[ cbn ].om_off );
513: # ifdef DEBUG
514: if ( ppcdebug ) {
515: fprintf( ppcdstream , "P2FLBRAC | %d | %d\n" , MAXTP2REG , ftnno );
516: fprintf( ppcdstream , "%d\n"
517: , BITSPERBYTE * -sizes[ cbn ].om_off );
518: }
519: # endif
520: }
521:
522: /*
523: * emit a right bracket operator
524: * which for the binary (fortran) interface
525: * doesn't have any (label) arguments,
526: * it just forces the stack allocate and register mask
527: */
528: putrbracket()
529: {
530:
531: emitword( P2FRBRAC );
532: # ifdef DEBUG
533: if ( ppcdebug ) {
534: fprintf( ppcdstream , "P2FRBRAC\n" );
535: }
536: # endif
537: }
538:
539: /*
540: * emit an eof operator
541: */
542: puteof()
543: {
544:
545: emitword( P2FEOF );
546: # ifdef DEBUG
547: if ( ppcdebug ) {
548: fprintf( ppcdstream , "P2FEOF\n" );
549: }
550: # endif
551: }
552:
553: /*
554: * emit a dot operator,
555: * with a source file line number and name
556: * from globals filename and line
557: */
558: putexpr()
559: {
560: int length = str4len( filename );
561:
562: emitword( TOF77( P2FEXPR , length , line ) );
563: # ifdef DEBUG
564: if ( ppcdebug ) {
565: fprintf( ppcdstream , "P2FEXPR | %d | %d\n" , length , line );
566: }
567: # endif
568: emitstring( filename );
569: }
570:
571: /*
572: * put out a leaf node
573: */
574: putleaf( op , lval , rval , type , name )
575: int op;
576: int lval;
577: int rval;
578: int type;
579: char *name;
580: {
581: switch ( op ) {
582: default:
583: panic( "[putleaf]" );
584: case P2ICON:
585: emitword( TOF77( P2ICON , name != NIL , type ) );
586: emitword( lval );
587: # ifdef DEBUG
588: if ( ppcdebug ) {
589: fprintf( ppcdstream , "P2ICON | %d | %d\n"
590: , name != NIL , type );
591: fprintf( ppcdstream , "%d\n" , lval );
592: }
593: # endif
594: if ( name )
595: emitname( name );
596: break;
597: case P2NAME:
598: emitword( TOF77( P2NAME , lval != 0 , type ) );
599: if ( lval )
600: emitword( lval );
601: # ifdef DEBUG
602: if ( ppcdebug ) {
603: fprintf( ppcdstream , "P2NAME | %d | %d\n"
604: , lval != 0 , type );
605: if ( lval )
606: fprintf( ppcdstream , "%d\n" , lval );
607: }
608: # endif
609: emitname( name );
610: break;
611: case P2REG:
612: emitword( TOF77( P2REG , rval , type ) );
613: # ifdef DEBUG
614: if ( ppcdebug ) {
615: fprintf( ppcdstream , "P2REG | %d | %d\n" , rval , type );
616: }
617: # endif
618: break;
619: }
620: }
621:
622: /*
623: * put a typed operator to the ppcstream
624: */
625: putop( op , type )
626: int op;
627: int type;
628: {
629:
630: emitword( TOF77( op , 0 , type ) );
631: # ifdef DEBUG
632: if ( ppcdebug ) {
633: fprintf( ppcdstream , "%d | 0 | %d\n" , op , type );
634: }
635: # endif
636: }
637:
638:
639: /*
640: * puts a long word on the ppcstream
641: */
642: emitword( word )
643: long word;
644: {
645:
646: putw( word , ppcstream );
647: };
648:
649: /*
650: * put a length 0 mod 4 null padded string onto the ppcstream
651: * this would use
652: * fprintf( ppcstream , "%*s" , -str4len( string ) , string )
653: * except that doesn't work, and also it wants to be padded with nulls.
654: */
655: emitstring( string )
656: char *string;
657: {
658: int slen = strlen( string );
659: int wlen = ( slen + 3 ) / 4;
660: int plen = ( wlen * 4 ) - slen;
661: char *cp;
662: int p;
663:
664: for ( cp = string ; *cp ; cp++ )
665: putc( *cp , ppcstream );
666: for ( p = 1 ; p <= plen ; p++ )
667: putc( '\0' , ppcstream );
668: # ifdef DEBUG
669: if ( ppcdebug ) {
670: fprintf( ppcdstream , "\"%s" , string );
671: for ( p = 1 ; p <= plen ; p++ )
672: fprintf( ppcdstream , "\\0" );
673: fprintf( ppcdstream , "\"\n" );
674: }
675: # endif
676: }
677:
678: /*
679: * puts a blank-padded 8 character name on the ppcstream
680: */
681: emitname( name )
682: char *name;
683: {
684:
685: fprintf( ppcstream , "%-8.8s" , name );
686: # ifdef DEBUG
687: if ( ppcdebug ) {
688: fprintf( ppcdstream , "<%-8.8s>\n" , name );
689: }
690: # endif
691: }
692:
693: #endif PPC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.