don't throw away float <-> double conversions for FORTRAN.
[unix-history] / usr / src / old / pcc / ccom.vax / code.c
CommitLineData
9ad0032c 1static char *sccsid ="@(#)code.c 1.2 (Berkeley) %G%";
7c801adb
ML
2# include "mfile1"
3# include <sys/types.h>
4# include <a.out.h>
5# include <stab.h>
6
7int proflg = 0; /* are we generating profiling code? */
8int strftn = 0; /* is the current function one which returns a value */
9int gdebug;
10int fdefflag; /* are we within a function definition ? */
11char NULLNAME[8];
12int labelno;
13
14branch( n ){
15 /* output a branch to label n */
16 /* exception is an ordinary function branching to retlab: then, return */
17 if( n == retlab && !strftn ){
18 printf( " ret\n" );
19 }
20 else printf( " jbr L%d\n", n );
21 }
22
23int lastloc = { -1 };
24
25short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
26#define LOG2SZ 9
27
28defalign(n) {
29 /* cause the alignment to become a multiple of n */
30 n /= SZCHAR;
31 if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 );
32 }
33
34locctr( l ){
35 register temp;
36 /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
37
38 if( l == lastloc ) return(l);
39 temp = lastloc;
40 lastloc = l;
41 switch( l ){
42
43 case PROG:
44 printf( " .text\n" );
45 psline();
46 break;
47
48 case DATA:
49 case ADATA:
50 printf( " .data\n" );
51 break;
52
53 case STRNG:
54 printf( " .data 1\n" );
55 break;
56
57 case ISTRNG:
58 printf( " .data 2\n" );
59 break;
60
61 case STAB:
62 printf( " .stab\n" );
63 break;
64
65 default:
66 cerror( "illegal location counter" );
67 }
68
69 return( temp );
70 }
71
72deflab( n ){
73 /* output something to define the current position as label n */
74 printf( "L%d:\n", n );
75 }
76
77int crslab = 10;
78
79getlab(){
80 /* return a number usable for a label */
81 return( ++crslab );
82 }
83
84
85int ent_mask[] = {
86 0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
87
88int reg_use = 11;
89
90efcode(){
91 /* code for the end of a function */
92
93 if( strftn ){ /* copy output (in R2) to caller */
94 register NODE *l, *r;
95 register struct symtab *p;
96 register TWORD t;
97 register int j;
98 int i;
99
100 p = &stab[curftn];
101 t = p->stype;
102 t = DECREF(t);
103
104 deflab( retlab );
105
106 i = getlab(); /* label for return area */
107#ifndef LCOMM
108 printf(" .data\n" );
109 printf(" .align 2\n" );
110 printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR );
111 printf(" .text\n" );
112#else
113 { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR;
114 if (sz % sizeof (int))
115 sz += sizeof (int) - (sz % sizeof (int));
116 printf(" .lcomm L%d,%d\n", i, sz);
117 }
118#endif
119 psline();
120 printf(" movab L%d,r1\n", i);
121
122 reached = 1;
123 l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
124 l->tn.rval = 1; /* R1 */
125 l->tn.lval = 0; /* no offset */
126 r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff );
127 r->tn.rval = 0; /* R0 */
128 r->tn.lval = 0;
129 l = buildtree( UNARY MUL, l, NIL );
130 r = buildtree( UNARY MUL, r, NIL );
131 l = buildtree( ASSIGN, l, r );
132 l->in.op = FREE;
133 ecomp( l->in.left );
134 printf( " movab L%d,r0\n", i );
135 /* turn off strftn flag, so return sequence will be generated */
136 strftn = 0;
137 }
138 branch( retlab );
139#ifndef VMS
140 printf( " .set L%d,0x%x\n", ftnno, ent_mask[reg_use] );
141#else
142 printf( " .set L%d,%d # Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use] );
143 /* KLS kludge, under VMS if you use regs 2-5, you must save them. */
144#endif
145 reg_use = 11;
146 p2bend();
147 fdefflag = 0;
148 }
149
150int ftlab1, ftlab2;
151
152bfcode( a, n ) int a[]; {
153 /* code for the beginning of a function; a is an array of
154 indices in stab for the arguments; n is the number */
155 register i;
156 register temp;
157 register struct symtab *p;
158 int off;
159 char *toreg();
160
161 locctr( PROG );
162 p = &stab[curftn];
163 printf( " .align 1\n");
164 defnam( p );
165 temp = p->stype;
166 temp = DECREF(temp);
167 strftn = (temp==STRTY) || (temp==UNIONTY);
168
169 retlab = getlab();
170
171 /* routine prolog */
172
173 printf( " .word L%d\n", ftnno);
7c801adb
ML
174 ftlab1 = getlab();
175 ftlab2 = getlab();
176 printf( " jbr L%d\n", ftlab1);
177 printf( "L%d:\n", ftlab2);
178 if( proflg ) { /* profile code */
179 i = getlab();
180 printf(" movab L%d,r0\n", i);
181 printf(" jsb mcount\n");
182 printf(" .data\n");
183 printf(" .align 2\n");
184 printf("L%d: .long 0\n", i);
185 printf(" .text\n");
186 psline();
187 }
188
189 off = ARGINIT;
190
191 for( i=0; i<n; ++i ){
192 p = &stab[a[i]];
193 if( p->sclass == REGISTER ){
194 temp = p->offset; /* save register number */
195 p->sclass = PARAM; /* forget that it is a register */
196 p->offset = NOOFFSET;
197 oalloc( p, &off );
198/*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp );
199 p->offset = temp; /* remember register number */
200 p->sclass = REGISTER; /* remember that it is a register */
201 }
202 else if( p->stype == STRTY || p->stype == UNIONTY ) {
203 p->offset = NOOFFSET;
204 if( oalloc( p, &off ) ) cerror( "bad argument" );
205 SETOFF( off, ALSTACK );
206 }
207 else {
208 if( oalloc( p, &off ) ) cerror( "bad argument" );
209 }
210
211 }
9ad0032c
SL
212 if (gdebug) {
213#ifdef STABDOT
214 pstabdot(N_SLINE, lineno);
215#else
216 pstab(NULLNAME, N_SLINE);
217 printf("0,%d,LL%d\n", lineno, labelno);
218 printf("LL%d:\n", labelno++);
219#endif
220 }
7c801adb
ML
221 fdefflag = 1;
222 }
223
224bccode(){ /* called just before the first executable statment */
225 /* by now, the automatics and register variables are allocated */
226 SETOFF( autooff, SZINT );
227 /* set aside store area offset */
228 p2bbeg( autooff, regvar );
229 reg_use = (reg_use > regvar ? regvar : reg_use);
230 }
231
232ejobcode( flag ){
233 /* called just before final exit */
234 /* flag is 1 if errors, 0 if none */
235 }
236
237aobeg(){
238 /* called before removing automatics from stab */
239 }
240
241aocode(p) struct symtab *p; {
242 /* called when automatic p removed from stab */
243 }
244
245aoend(){
246 /* called after removing all automatics from stab */
247 }
248
249defnam( p ) register struct symtab *p; {
250 /* define the current location as the name p->sname */
251
252 if( p->sclass == EXTDEF ){
253 printf( " .globl %s\n", exname( p->sname ) );
254 }
255 if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset );
256 else printf( "%s:\n", exname( p->sname ) );
257
258 }
259
260bycode( t, i ){
261#ifdef ASSTRINGS
262static int lastoctal = 0;
263#endif
264
265 /* put byte i+1 in a string */
266
267#ifdef ASSTRINGS
268
269 i &= 077;
270 if ( t < 0 ){
271 if ( i != 0 ) printf( "\"\n" );
272 } else {
273 if ( i == 0 ) printf("\t.ascii\t\"");
274 if ( t == '\\' || t == '"'){
275 lastoctal = 0;
276 printf("\\%c", t);
277 }
278 /*
279 * We escape the colon in strings so that
280 * c2 will, in its infinite wisdom, interpret
281 * the characters preceding the colon as a label.
282 * If we didn't escape the colon, c2 would
283 * throw away any trailing blanks or tabs after
284 * the colon, but reconstruct a assembly
285 * language semantically correct program.
286 * C2 hasn't been taught about strings.
287 */
288 else if ( t == ':' || t < 040 || t >= 0177 ){
289 lastoctal++;
290 printf("\\%o",t);
291 }
292 else if ( lastoctal && '0' <= t && t <= '9' ){
293 lastoctal = 0;
294 printf("\"\n\t.ascii\t\"%c", t );
295 }
296 else
297 {
298 lastoctal = 0;
299 putchar(t);
300 }
301 if ( i == 077 ) printf("\"\n");
302 }
303#else
304
305 i &= 07;
306 if( t < 0 ){ /* end of the string */
307 if( i != 0 ) printf( "\n" );
308 }
309
310 else { /* stash byte t into string */
311 if( i == 0 ) printf( " .byte " );
312 else printf( "," );
313 printf( "0x%x", t );
314 if( i == 07 ) printf( "\n" );
315 }
316#endif
317 }
318
319zecode( n ){
320 /* n integer words of zeros */
321 OFFSZ temp;
322 if( n <= 0 ) return;
323 printf( " .space %d\n", (SZINT/SZCHAR)*n );
324 temp = n;
325 inoff += temp*SZINT;
326 }
327
328fldal( t ) unsigned t; { /* return the alignment of field of type t */
329 uerror( "illegal field type" );
330 return( ALINT );
331 }
332
333fldty( p ) struct symtab *p; { /* fix up type of field p */
334 ;
335 }
336
337where(c){ /* print location of error */
338 /* c is either 'u', 'c', or 'w' */
339 /* GCOS version */
340 fprintf( stderr, "%s, line %d: ", ftitle, lineno );
341 }
342
343
344/* tbl - toreg() returns a pointer to a char string
345 which is the correct "register move" for the passed type
346 */
347struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] =
348 {
349 CHAR, "cvtbl",
350 SHORT, "cvtwl",
351 INT, "movl",
352 LONG, "movl",
353 FLOAT, "movf",
354 DOUBLE, "movd",
355 UCHAR, "movzbl",
356 USHORT, "movzwl",
357 UNSIGNED, "movl",
358 ULONG, "movl",
359 -1, ""
360 };
361
362char
363*toreg(type)
364 TWORD type;
365{
366 struct type_move *p;
367
368 for ( p=toreg_strs; p->fromtype > 0; p++)
369 if (p->fromtype == type) return(p->tostrng);
370
371 /* type not found, must be a pointer type */
372 return("movl");
373}
374/* tbl */
375
376
377main( argc, argv ) char *argv[]; {
378#ifdef BUFSTDERR
379 char errbuf[BUFSIZ];
380 setbuf(stderr, errbuf);
381#endif
382 return(mainp1( argc, argv ));
383 }
384
385struct sw heapsw[SWITSZ]; /* heap for switches */
386
387genswitch(p,n) register struct sw *p;{
388 /* p points to an array of structures, each consisting
389 of a constant value and a label.
390 The first is >=0 if there is a default label;
391 its value is the label number
392 The entries p[1] to p[n] are the nontrivial cases
393 */
394 register i;
395 register CONSZ j, range;
396 register dlab, swlab;
397
398 range = p[n].sval-p[1].sval;
399
400 if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */
401
402 swlab = getlab();
403 dlab = p->slab >= 0 ? p->slab : getlab();
404
405 /* already in r0 */
406 printf(" casel r0,$%ld,$%ld\n", p[1].sval, range);
407 printf("L%d:\n", swlab);
408 for( i=1,j=p[1].sval; i<=n; j++) {
409 printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab),
410 swlab);
411 }
412
413 if( p->slab >= 0 ) branch( dlab );
414 else printf("L%d:\n", dlab);
415 return;
416
417 }
418
419 if( n>8 ) { /* heap switch */
420
421 heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
422 makeheap(p, n, 1); /* build heap */
423
424 walkheap(1, n); /* produce code */
425
426 if( p->slab >= 0 )
427 branch( dlab );
428 else
429 printf("L%d:\n", dlab);
430 return;
431 }
432
433 /* debugging code */
434
435 /* out for the moment
436 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
437 */
438
439 /* simple switch code */
440
441 for( i=1; i<=n; ++i ){
442 /* already in r0 */
443
444 printf( " cmpl r0,$" );
445 printf( CONFMT, p[i].sval );
446 printf( "\n jeql L%d\n", p[i].slab );
447 }
448
449 if( p->slab>=0 ) branch( p->slab );
450 }
451
452makeheap(p, m, n)
453register struct sw *p;
454{
455 register int q;
456
457 q = select(m);
458 heapsw[n] = p[q];
459 if( q>1 ) makeheap(p, q-1, 2*n);
460 if( q<m ) makeheap(p+q, m-q, 2*n+1);
461}
462
463select(m) {
464 register int l,i,k;
465
466 for(i=1; ; i*=2)
467 if( (i-1) > m ) break;
468 l = ((k = i/2 - 1) + 1)/2;
469 return( l + (m-k < l ? m-k : l));
470}
471
472walkheap(start, limit)
473{
474 int label;
475
476
477 if( start > limit ) return;
478 printf(" cmpl r0,$%d\n", heapsw[start].sval);
479 printf(" jeql L%d\n", heapsw[start].slab);
480 if( (2*start) > limit ) {
481 printf(" jbr L%d\n", heapsw[0].slab);
482 return;
483 }
484 if( (2*start+1) <= limit ) {
485 label = getlab();
486 printf(" jgtr L%d\n", label);
487 } else
488 printf(" jgtr L%d\n", heapsw[0].slab);
489 walkheap( 2*start, limit);
490 if( (2*start+1) <= limit ) {
491 printf("L%d:\n", label);
492 walkheap( 2*start+1, limit);
493 }
494}