1 | /* $Id: local2.c,v 1.11 2008/11/22 16:12:25 ragge Exp $ */
|
---|
2 | /*
|
---|
3 | * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
|
---|
4 | *
|
---|
5 | * Redistribution and use in source and binary forms, with or without
|
---|
6 | * modification, are permitted provided that the following conditions
|
---|
7 | * are met:
|
---|
8 | *
|
---|
9 | * Redistributions of source code and documentation must retain the above
|
---|
10 | * copyright notice, this list of conditions and the following disclaimer.
|
---|
11 | * Redistributions in binary form must reproduce the above copyright
|
---|
12 | * notice, this list of conditionsand the following disclaimer in the
|
---|
13 | * documentation and/or other materials provided with the distribution.
|
---|
14 | * All advertising materials mentioning features or use of this software
|
---|
15 | * must display the following acknowledgement:
|
---|
16 | * This product includes software developed or owned by Caldera
|
---|
17 | * International, Inc.
|
---|
18 | * Neither the name of Caldera International, Inc. nor the names of other
|
---|
19 | * contributors may be used to endorse or promote products derived from
|
---|
20 | * this software without specific prior written permission.
|
---|
21 | *
|
---|
22 | * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
---|
23 | * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
---|
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
---|
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
---|
26 | * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
|
---|
27 | * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
30 | * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
|
---|
31 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
---|
32 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
---|
33 | * POSSIBILITY OF SUCH DAMAGE.
|
---|
34 | */
|
---|
35 |
|
---|
36 | # include "pass2.h"
|
---|
37 | # include "ctype.h"
|
---|
38 | /* a lot of the machine dependent parts of the second pass */
|
---|
39 |
|
---|
40 | static void prtype(NODE *n);
|
---|
41 | static void acon(NODE *p);
|
---|
42 |
|
---|
43 | /*
|
---|
44 | * Print out the prolog assembler.
|
---|
45 | * addto and regoff are already calculated.
|
---|
46 | */
|
---|
47 | void
|
---|
48 | prologue(struct interpass_prolog *ipp)
|
---|
49 | {
|
---|
50 | if (ipp->ipp_vis)
|
---|
51 | printf(" .globl %s\n", ipp->ipp_name);
|
---|
52 | printf(" .align 4\n");
|
---|
53 | printf("%s:\n", ipp->ipp_name);
|
---|
54 | printf(" .word 0x%x\n", ipp->ipp_regs[0]);
|
---|
55 | if (p2maxautooff)
|
---|
56 | printf(" subl2 $%d,%%sp\n", p2maxautooff);
|
---|
57 | }
|
---|
58 |
|
---|
59 | /*
|
---|
60 | * Called after all instructions in a function are emitted.
|
---|
61 | * Generates code for epilog here.
|
---|
62 | */
|
---|
63 | void
|
---|
64 | eoftn(struct interpass_prolog *ipp)
|
---|
65 | {
|
---|
66 | if (ipp->ipp_ip.ip_lbl == 0)
|
---|
67 | return; /* no code needs to be generated */
|
---|
68 | printf(" ret\n");
|
---|
69 | }
|
---|
70 |
|
---|
71 | struct hoptab { int opmask; char * opstring; } ioptab[] = {
|
---|
72 |
|
---|
73 | { PLUS, "add", },
|
---|
74 | { MINUS, "sub", },
|
---|
75 | { MUL, "mul", },
|
---|
76 | { DIV, "div", },
|
---|
77 | { OR, "bis", },
|
---|
78 | { ER, "xor", },
|
---|
79 | { AND, "bic", },
|
---|
80 | { -1, "" },
|
---|
81 | };
|
---|
82 |
|
---|
83 | void
|
---|
84 | hopcode( f, o ){
|
---|
85 | /* output the appropriate string from the above table */
|
---|
86 |
|
---|
87 | register struct hoptab *q;
|
---|
88 |
|
---|
89 | for( q = ioptab; q->opmask>=0; ++q ){
|
---|
90 | if( q->opmask == o ){
|
---|
91 | printf( "%s", q->opstring );
|
---|
92 | /* tbl
|
---|
93 | if( f == 'F' ) printf( "e" );
|
---|
94 | else if( f == 'D' ) printf( "d" );
|
---|
95 | tbl */
|
---|
96 | /* tbl */
|
---|
97 | switch( f ) {
|
---|
98 | case 'L':
|
---|
99 | case 'W':
|
---|
100 | case 'B':
|
---|
101 | case 'D':
|
---|
102 | case 'F':
|
---|
103 | printf("%c", tolower(f));
|
---|
104 | break;
|
---|
105 |
|
---|
106 | }
|
---|
107 | /* tbl */
|
---|
108 | return;
|
---|
109 | }
|
---|
110 | }
|
---|
111 | cerror( "no hoptab for %s", opst[o] );
|
---|
112 | }
|
---|
113 |
|
---|
114 | char *
|
---|
115 | rnames[] = { /* keyed to register number tokens */
|
---|
116 |
|
---|
117 | "r0", "r1", "r2", "r3", "r4", "r5",
|
---|
118 | "r6", "r7", "r8", "r9", "r10", "r11",
|
---|
119 | "ap", "fp", "sp", "pc",
|
---|
120 | /* The concatenated regs has the name of the lowest */
|
---|
121 | "r0", "r1", "r2", "r3", "r4", "r5",
|
---|
122 | "r6", "r7", "r8", "r9", "r10"
|
---|
123 | };
|
---|
124 |
|
---|
125 | int
|
---|
126 | tlen(p) NODE *p;
|
---|
127 | {
|
---|
128 | switch(p->n_type) {
|
---|
129 | case CHAR:
|
---|
130 | case UCHAR:
|
---|
131 | return(1);
|
---|
132 |
|
---|
133 | case SHORT:
|
---|
134 | case USHORT:
|
---|
135 | return(2);
|
---|
136 |
|
---|
137 | case DOUBLE:
|
---|
138 | case LDOUBLE:
|
---|
139 | case LONGLONG:
|
---|
140 | case ULONGLONG:
|
---|
141 | return(8);
|
---|
142 |
|
---|
143 | default:
|
---|
144 | return(4);
|
---|
145 | }
|
---|
146 | }
|
---|
147 |
|
---|
148 | static int
|
---|
149 | mixtypes(NODE *p, NODE *q)
|
---|
150 | {
|
---|
151 | TWORD tp, tq;
|
---|
152 |
|
---|
153 | tp = p->n_type;
|
---|
154 | tq = q->n_type;
|
---|
155 |
|
---|
156 | return( (tp==FLOAT || tp==DOUBLE) !=
|
---|
157 | (tq==FLOAT || tq==DOUBLE) );
|
---|
158 | }
|
---|
159 |
|
---|
160 | void
|
---|
161 | prtype(NODE *n)
|
---|
162 | {
|
---|
163 | switch (n->n_type)
|
---|
164 | {
|
---|
165 | case DOUBLE:
|
---|
166 | printf("d");
|
---|
167 | return;
|
---|
168 |
|
---|
169 | case FLOAT:
|
---|
170 | printf("f");
|
---|
171 | return;
|
---|
172 |
|
---|
173 | case LONG:
|
---|
174 | case ULONG:
|
---|
175 | case INT:
|
---|
176 | case UNSIGNED:
|
---|
177 | printf("l");
|
---|
178 | return;
|
---|
179 |
|
---|
180 | case SHORT:
|
---|
181 | case USHORT:
|
---|
182 | printf("w");
|
---|
183 | return;
|
---|
184 |
|
---|
185 | case CHAR:
|
---|
186 | case UCHAR:
|
---|
187 | printf("b");
|
---|
188 | return;
|
---|
189 |
|
---|
190 | default:
|
---|
191 | if ( !ISPTR( n->n_type ) ) cerror("zzzcode- bad type");
|
---|
192 | else {
|
---|
193 | printf("l");
|
---|
194 | return;
|
---|
195 | }
|
---|
196 | }
|
---|
197 | }
|
---|
198 |
|
---|
199 | void
|
---|
200 | zzzcode( p, c ) register NODE *p; {
|
---|
201 | int m;
|
---|
202 | int val;
|
---|
203 | switch( c ){
|
---|
204 |
|
---|
205 | case 'N': /* logical ops, turned into 0-1 */
|
---|
206 | /* use register given by register 1 */
|
---|
207 | cbgen( 0, m=getlab2());
|
---|
208 | deflab( p->n_label );
|
---|
209 | printf( " clrl %s\n", rnames[getlr( p, '1' )->n_rval] );
|
---|
210 | deflab( m );
|
---|
211 | return;
|
---|
212 |
|
---|
213 | case 'A':
|
---|
214 | {
|
---|
215 | register NODE *l, *r;
|
---|
216 |
|
---|
217 | if (xdebug) e2print(p, 0, &val, &val);
|
---|
218 | r = getlr(p, 'R');
|
---|
219 | if (optype(p->n_op) == LTYPE || p->n_op == UMUL) {
|
---|
220 | l = resc;
|
---|
221 | l->n_type = (r->n_type==FLOAT || r->n_type==DOUBLE ? DOUBLE : INT);
|
---|
222 | } else
|
---|
223 | l = getlr(p, 'L');
|
---|
224 | if (r->n_op == ICON && r->n_name[0] == '\0') {
|
---|
225 | if (r->n_lval == 0) {
|
---|
226 | printf("clr");
|
---|
227 | prtype(l);
|
---|
228 | printf(" ");
|
---|
229 | adrput(stdout, l);
|
---|
230 | return;
|
---|
231 | }
|
---|
232 | if (r->n_lval < 0 && r->n_lval >= -63) {
|
---|
233 | printf("mneg");
|
---|
234 | prtype(l);
|
---|
235 | r->n_lval = -r->n_lval;
|
---|
236 | goto ops;
|
---|
237 | }
|
---|
238 | r->n_type = (r->n_lval < 0 ?
|
---|
239 | (r->n_lval >= -128 ? CHAR
|
---|
240 | : (r->n_lval >= -32768 ? SHORT
|
---|
241 | : INT )) : r->n_type);
|
---|
242 | r->n_type = (r->n_lval >= 0 ?
|
---|
243 | (r->n_lval <= 63 ? INT
|
---|
244 | : ( r->n_lval <= 127 ? CHAR
|
---|
245 | : (r->n_lval <= 255 ? UCHAR
|
---|
246 | : (r->n_lval <= 32767 ? SHORT
|
---|
247 | : (r->n_lval <= 65535 ? USHORT
|
---|
248 | : INT ))))) : r->n_type );
|
---|
249 | }
|
---|
250 | if (l->n_op == REG && l->n_type != FLOAT && l->n_type != DOUBLE)
|
---|
251 | l->n_type = INT;
|
---|
252 | if (!mixtypes(l,r))
|
---|
253 | {
|
---|
254 | if (tlen(l) == tlen(r))
|
---|
255 | {
|
---|
256 | printf("mov");
|
---|
257 | prtype(l);
|
---|
258 | goto ops;
|
---|
259 | }
|
---|
260 | else if (tlen(l) > tlen(r) && ISUNSIGNED(r->n_type))
|
---|
261 | {
|
---|
262 | printf("movz");
|
---|
263 | }
|
---|
264 | else
|
---|
265 | {
|
---|
266 | printf("cvt");
|
---|
267 | }
|
---|
268 | }
|
---|
269 | else
|
---|
270 | {
|
---|
271 | printf("cvt");
|
---|
272 | }
|
---|
273 | prtype(r);
|
---|
274 | prtype(l);
|
---|
275 | ops:
|
---|
276 | printf(" ");
|
---|
277 | adrput(stdout, r);
|
---|
278 | printf(",");
|
---|
279 | adrput(stdout, l);
|
---|
280 | return;
|
---|
281 | }
|
---|
282 |
|
---|
283 | case 'C': /* num words pushed on arg stack */
|
---|
284 | if (p->n_op == STCALL || p->n_op == USTCALL)
|
---|
285 | p->n_qual++;
|
---|
286 | printf("$%d", p->n_qual);
|
---|
287 | break;
|
---|
288 |
|
---|
289 | case 'D': /* INCR and DECR */
|
---|
290 | zzzcode(p->n_left, 'A');
|
---|
291 | printf("\n ");
|
---|
292 |
|
---|
293 | #if 0
|
---|
294 | case 'E': /* INCR and DECR, FOREFF */
|
---|
295 | if (p->n_right->n_lval == 1)
|
---|
296 | {
|
---|
297 | printf("%s", (p->n_op == INCR ? "inc" : "dec") );
|
---|
298 | prtype(p->n_left);
|
---|
299 | printf(" ");
|
---|
300 | adrput(stdout, p->n_left);
|
---|
301 | return;
|
---|
302 | }
|
---|
303 | printf("%s", (p->n_op == INCR ? "add" : "sub") );
|
---|
304 | prtype(p->n_left);
|
---|
305 | printf("2 ");
|
---|
306 | adrput(stdout, p->n_right);
|
---|
307 | printf(",");
|
---|
308 | adrput(p->n_left);
|
---|
309 | return;
|
---|
310 | #endif
|
---|
311 |
|
---|
312 | case 'F': /* register type of right operand */
|
---|
313 | {
|
---|
314 | register NODE *n;
|
---|
315 | extern int xdebug;
|
---|
316 | register int ty;
|
---|
317 |
|
---|
318 | n = getlr( p, 'R' );
|
---|
319 | ty = n->n_type;
|
---|
320 |
|
---|
321 | if (xdebug) printf("->%d<-", ty);
|
---|
322 |
|
---|
323 | if ( ty==DOUBLE) printf("d");
|
---|
324 | else if ( ty==FLOAT ) printf("f");
|
---|
325 | else printf("l");
|
---|
326 | return;
|
---|
327 | }
|
---|
328 |
|
---|
329 | case 'J': /* jump or ret? */
|
---|
330 | {
|
---|
331 | extern struct interpass_prolog *epp;
|
---|
332 | struct interpass *ip =
|
---|
333 | DLIST_PREV((struct interpass *)epp, qelem);
|
---|
334 | if (ip->type != IP_DEFLAB ||
|
---|
335 | ip->ip_lbl != getlr(p, 'L')->n_lval)
|
---|
336 | expand(p, FOREFF, "jbr LL");
|
---|
337 | else
|
---|
338 | printf("ret");
|
---|
339 | }
|
---|
340 | break;
|
---|
341 |
|
---|
342 | case 'L': /* type of left operand */
|
---|
343 | case 'R': /* type of right operand */
|
---|
344 | {
|
---|
345 | register NODE *n;
|
---|
346 | extern int xdebug;
|
---|
347 |
|
---|
348 | n = getlr ( p, c);
|
---|
349 | if (xdebug) printf("->%d<-", n->n_type);
|
---|
350 |
|
---|
351 | prtype(n);
|
---|
352 | return;
|
---|
353 | }
|
---|
354 |
|
---|
355 | case 'Z': /* complement mask for bit instr */
|
---|
356 | printf("$%Ld", ~p->n_right->n_lval);
|
---|
357 | return;
|
---|
358 |
|
---|
359 | case 'U': /* 32 - n, for unsigned right shifts */
|
---|
360 | printf("$" CONFMT, 32 - p->n_right->n_lval );
|
---|
361 | return;
|
---|
362 |
|
---|
363 | case 'T': /* rounded structure length for arguments */
|
---|
364 | {
|
---|
365 | int size;
|
---|
366 |
|
---|
367 | size = p->n_stsize;
|
---|
368 | SETOFF( size, 4);
|
---|
369 | printf("$%d", size);
|
---|
370 | return;
|
---|
371 | }
|
---|
372 |
|
---|
373 | case 'S': /* structure assignment */
|
---|
374 | {
|
---|
375 | register NODE *l, *r;
|
---|
376 | register int size;
|
---|
377 |
|
---|
378 | l = r = NULL; /* XXX gcc */
|
---|
379 | if( p->n_op == STASG ){
|
---|
380 | l = p->n_left;
|
---|
381 | r = p->n_right;
|
---|
382 |
|
---|
383 | }
|
---|
384 | else if( p->n_op == STARG ){ /* store an arg into a temporary */
|
---|
385 | l = getlr( p, '3' );
|
---|
386 | r = p->n_left;
|
---|
387 | }
|
---|
388 | else cerror( "STASG bad" );
|
---|
389 |
|
---|
390 | if( r->n_op == ICON ) r->n_op = NAME;
|
---|
391 | else if( r->n_op == REG ) r->n_op = OREG;
|
---|
392 | else if( r->n_op != OREG ) cerror( "STASG-r" );
|
---|
393 |
|
---|
394 | size = p->n_stsize;
|
---|
395 |
|
---|
396 | if( size <= 0 || size > 65535 )
|
---|
397 | cerror("structure size <0=0 or >65535");
|
---|
398 |
|
---|
399 | switch(size) {
|
---|
400 | case 1:
|
---|
401 | printf(" movb ");
|
---|
402 | break;
|
---|
403 | case 2:
|
---|
404 | printf(" movw ");
|
---|
405 | break;
|
---|
406 | case 4:
|
---|
407 | printf(" movl ");
|
---|
408 | break;
|
---|
409 | case 8:
|
---|
410 | printf(" movq ");
|
---|
411 | break;
|
---|
412 | default:
|
---|
413 | printf(" movc3 $%d,", size);
|
---|
414 | break;
|
---|
415 | }
|
---|
416 | adrput(stdout, r);
|
---|
417 | printf(",");
|
---|
418 | adrput(stdout, l);
|
---|
419 | printf("\n");
|
---|
420 |
|
---|
421 | if( r->n_op == NAME ) r->n_op = ICON;
|
---|
422 | else if( r->n_op == OREG ) r->n_op = REG;
|
---|
423 |
|
---|
424 | }
|
---|
425 | break;
|
---|
426 |
|
---|
427 | default:
|
---|
428 | comperr("illegal zzzcode '%c'", c);
|
---|
429 | }
|
---|
430 | }
|
---|
431 |
|
---|
432 | void
|
---|
433 | rmove( int rt,int rs, TWORD t ){
|
---|
434 | printf( " %s %s,%s\n",
|
---|
435 | (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
|
---|
436 | rnames[rs], rnames[rt] );
|
---|
437 | }
|
---|
438 |
|
---|
439 | #if 0
|
---|
440 | setregs(){ /* set up temporary registers */
|
---|
441 | fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
|
---|
442 | ;
|
---|
443 | }
|
---|
444 |
|
---|
445 | szty(t){ /* size, in registers, needed to hold thing of type t */
|
---|
446 | return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
|
---|
447 | }
|
---|
448 | #endif
|
---|
449 |
|
---|
450 | int
|
---|
451 | rewfld( p ) NODE *p; {
|
---|
452 | return(1);
|
---|
453 | }
|
---|
454 |
|
---|
455 | #if 0
|
---|
456 | callreg(p) NODE *p; {
|
---|
457 | return( R0 );
|
---|
458 | }
|
---|
459 |
|
---|
460 | base( p ) register NODE *p; {
|
---|
461 | register int o = p->op;
|
---|
462 |
|
---|
463 | if( (o==ICON && p->name[0] != '\0')) return( 100 ); /* ie no base reg */
|
---|
464 | if( o==REG ) return( p->rval );
|
---|
465 | if( (o==PLUS || o==MINUS) && p->left->op == REG && p->right->op==ICON)
|
---|
466 | return( p->left->rval );
|
---|
467 | if( o==OREG && !R2TEST(p->rval) && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
|
---|
468 | return( p->rval + 0200*1 );
|
---|
469 | if( o==INCR && p->left->op==REG ) return( p->left->rval + 0200*2 );
|
---|
470 | if( o==ASG MINUS && p->left->op==REG) return( p->left->rval + 0200*4 );
|
---|
471 | if( o==UNARY MUL && p->left->op==INCR && p->left->left->op==REG
|
---|
472 | && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
|
---|
473 | return( p->left->left->rval + 0200*(1+2) );
|
---|
474 | return( -1 );
|
---|
475 | }
|
---|
476 |
|
---|
477 | offset( p, tyl ) register NODE *p; int tyl; {
|
---|
478 |
|
---|
479 | if( tyl==1 && p->op==REG && (p->type==INT || p->type==UNSIGNED) ) return( p->rval );
|
---|
480 | if( (p->op==LS && p->left->op==REG && (p->left->type==INT || p->left->type==UNSIGNED) &&
|
---|
481 | (p->right->op==ICON && p->right->name[0]=='\0')
|
---|
482 | && (1<<p->right->lval)==tyl))
|
---|
483 | return( p->left->rval );
|
---|
484 | return( -1 );
|
---|
485 | }
|
---|
486 | #endif
|
---|
487 |
|
---|
488 | #if 0
|
---|
489 | void
|
---|
490 | makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
|
---|
491 | register NODE *t;
|
---|
492 | NODE *f;
|
---|
493 |
|
---|
494 | p->n_op = OREG;
|
---|
495 | f = p->n_left; /* have to free this subtree later */
|
---|
496 |
|
---|
497 | /* init base */
|
---|
498 | switch (q->n_op) {
|
---|
499 | case ICON:
|
---|
500 | case REG:
|
---|
501 | case OREG:
|
---|
502 | t = q;
|
---|
503 | break;
|
---|
504 |
|
---|
505 | case MINUS:
|
---|
506 | q->n_right->n_lval = -q->n_right->n_lval;
|
---|
507 | case PLUS:
|
---|
508 | t = q->n_right;
|
---|
509 | break;
|
---|
510 |
|
---|
511 | case UMUL:
|
---|
512 | t = q->n_left->n_left;
|
---|
513 | break;
|
---|
514 |
|
---|
515 | default:
|
---|
516 | cerror("illegal makeor2");
|
---|
517 | t = NULL; /* XXX gcc */
|
---|
518 | }
|
---|
519 |
|
---|
520 | p->n_lval = t->n_lval;
|
---|
521 | p->n_name = t->n_name;
|
---|
522 |
|
---|
523 | /* init offset */
|
---|
524 | p->n_rval = R2PACK( (b & 0177), o, (b>>7) );
|
---|
525 |
|
---|
526 | tfree(f);
|
---|
527 | return;
|
---|
528 | }
|
---|
529 |
|
---|
530 | int
|
---|
531 | canaddr( p ) NODE *p; {
|
---|
532 | register int o = p->n_op;
|
---|
533 |
|
---|
534 | if( o==NAME || o==REG || o==ICON || o==OREG || (o==UMUL && shumul(p->n_left, STARNM|SOREG)) ) return(1);
|
---|
535 | return(0);
|
---|
536 | }
|
---|
537 |
|
---|
538 | shltype( o, p ) register NODE *p; {
|
---|
539 | return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UMUL && shumul(p->n_left, STARNM|SOREG)) );
|
---|
540 | }
|
---|
541 | #endif
|
---|
542 |
|
---|
543 | int
|
---|
544 | fldexpand(NODE *p, int cookie, char **cp)
|
---|
545 | {
|
---|
546 | return 0;
|
---|
547 | }
|
---|
548 |
|
---|
549 | int
|
---|
550 | flshape( p ) register NODE *p; {
|
---|
551 | return( p->n_op == REG || p->n_op == NAME || p->n_op == ICON ||
|
---|
552 | (p->n_op == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)) );
|
---|
553 | }
|
---|
554 |
|
---|
555 | int
|
---|
556 | shtemp( p ) register NODE *p; {
|
---|
557 | if( p->n_op == STARG ) p = p->n_left;
|
---|
558 | return( p->n_op==NAME || p->n_op ==ICON || p->n_op == OREG || (p->n_op==UMUL && shumul(p->n_left, STARNM|SOREG)) );
|
---|
559 | }
|
---|
560 |
|
---|
561 | int
|
---|
562 | shumul( p, shape ) register NODE *p; int shape; {
|
---|
563 | register int o;
|
---|
564 | extern int xdebug;
|
---|
565 |
|
---|
566 | if (xdebug) {
|
---|
567 | printf("\nshumul:op=%d,lop=%d,rop=%d", p->n_op, p->n_left->n_op, p->n_right->n_op);
|
---|
568 | printf(" prname=%s,plty=%d, prlval=%lld\n", p->n_right->n_name, p->n_left->n_type, p->n_right->n_lval);
|
---|
569 | }
|
---|
570 |
|
---|
571 |
|
---|
572 | o = p->n_op;
|
---|
573 | if( o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON )
|
---|
574 | if (shape & STARNM)
|
---|
575 | return SRDIR;
|
---|
576 |
|
---|
577 | #ifdef notyet
|
---|
578 | if( ( o == INCR || o == ASG MINUS ) &&
|
---|
579 | ( p->n_left->n_op == REG && p->n_right->n_op == ICON ) &&
|
---|
580 | p->n_right->n_name[0] == '\0' )
|
---|
581 | {
|
---|
582 | switch (p->n_left->n_type)
|
---|
583 | {
|
---|
584 | case CHAR|PTR:
|
---|
585 | case UCHAR|PTR:
|
---|
586 | o = 1;
|
---|
587 | break;
|
---|
588 |
|
---|
589 | case SHORT|PTR:
|
---|
590 | case USHORT|PTR:
|
---|
591 | o = 2;
|
---|
592 | break;
|
---|
593 |
|
---|
594 | case INT|PTR:
|
---|
595 | case UNSIGNED|PTR:
|
---|
596 | case LONG|PTR:
|
---|
597 | case ULONG|PTR:
|
---|
598 | case FLOAT|PTR:
|
---|
599 | o = 4;
|
---|
600 | break;
|
---|
601 |
|
---|
602 | case DOUBLE|PTR:
|
---|
603 | o = 8;
|
---|
604 | break;
|
---|
605 |
|
---|
606 | default:
|
---|
607 | if ( ISPTR(p->n_left->n_type) ) {
|
---|
608 | o = 4;
|
---|
609 | break;
|
---|
610 | }
|
---|
611 | else return(0);
|
---|
612 | }
|
---|
613 | return( p->n_right->n_lval == o ? STARREG : 0);
|
---|
614 | }
|
---|
615 | #endif
|
---|
616 |
|
---|
617 | return( SRNOPE );
|
---|
618 | }
|
---|
619 |
|
---|
620 | void
|
---|
621 | adrcon( val ) CONSZ val; {
|
---|
622 | printf( "$" );
|
---|
623 | printf( CONFMT, val );
|
---|
624 | }
|
---|
625 |
|
---|
626 | void
|
---|
627 | conput(FILE *fp, NODE *p)
|
---|
628 | {
|
---|
629 | switch( p->n_op ){
|
---|
630 |
|
---|
631 | case ICON:
|
---|
632 | acon( p );
|
---|
633 | return;
|
---|
634 |
|
---|
635 | case REG:
|
---|
636 | printf( "%s", rnames[p->n_rval] );
|
---|
637 | return;
|
---|
638 |
|
---|
639 | default:
|
---|
640 | cerror( "illegal conput" );
|
---|
641 | }
|
---|
642 | }
|
---|
643 |
|
---|
644 | void
|
---|
645 | insput( p ) register NODE *p; {
|
---|
646 | cerror( "insput" );
|
---|
647 | }
|
---|
648 |
|
---|
649 | void
|
---|
650 | upput( p , size) register NODE *p; {
|
---|
651 | cerror( "upput" );
|
---|
652 | }
|
---|
653 |
|
---|
654 | void
|
---|
655 | adrput(FILE *fp, NODE *p)
|
---|
656 | {
|
---|
657 | register int r;
|
---|
658 | /* output an address, with offsets, from p */
|
---|
659 |
|
---|
660 | if( p->n_op == FLD ){
|
---|
661 | p = p->n_left;
|
---|
662 | }
|
---|
663 | switch( p->n_op ){
|
---|
664 |
|
---|
665 | case NAME:
|
---|
666 | acon( p );
|
---|
667 | return;
|
---|
668 |
|
---|
669 | case ICON:
|
---|
670 | /* addressable value of the constant */
|
---|
671 | if (p->n_name[0] == '\0') /* uses xxxab */
|
---|
672 | printf("$");
|
---|
673 | acon(p);
|
---|
674 | return;
|
---|
675 |
|
---|
676 | case REG:
|
---|
677 | printf( "%s", rnames[p->n_rval] );
|
---|
678 | return;
|
---|
679 |
|
---|
680 | case OREG:
|
---|
681 | r = p->n_rval;
|
---|
682 | if( R2TEST(r) ){ /* double indexing */
|
---|
683 | register int flags;
|
---|
684 |
|
---|
685 | flags = R2UPK3(r);
|
---|
686 | if( flags & 1 ) printf("*");
|
---|
687 | if( flags & 4 ) printf("-");
|
---|
688 | if( p->n_lval != 0 || p->n_name[0] != '\0' ) acon(p);
|
---|
689 | if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
|
---|
690 | if( flags & 2 ) printf("+");
|
---|
691 | printf( "[%s]", rnames[R2UPK2(r)] );
|
---|
692 | return;
|
---|
693 | }
|
---|
694 | if( r == AP ){ /* in the argument region */
|
---|
695 | if( p->n_lval <= 0 || p->n_name[0] != '\0' ) werror( "bad arg temp" );
|
---|
696 | printf( CONFMT, p->n_lval );
|
---|
697 | printf( "(ap)" );
|
---|
698 | return;
|
---|
699 | }
|
---|
700 | if( p->n_lval != 0 || p->n_name[0] != '\0') acon( p );
|
---|
701 | printf( "(%s)", rnames[p->n_rval] );
|
---|
702 | return;
|
---|
703 |
|
---|
704 | case UMUL:
|
---|
705 | /* STARNM or STARREG found */
|
---|
706 | if( tshape(p, STARNM) ) {
|
---|
707 | printf( "*" );
|
---|
708 | adrput(0, p->n_left);
|
---|
709 | }
|
---|
710 | else { /* STARREG - really auto inc or dec */
|
---|
711 | register NODE *q;
|
---|
712 |
|
---|
713 | /* tbl
|
---|
714 | p = p->n_left;
|
---|
715 | p->n_left->n_op = OREG;
|
---|
716 | if( p->n_op == INCR ) {
|
---|
717 | adrput( p->n_left );
|
---|
718 | printf( "+" );
|
---|
719 | }
|
---|
720 | else {
|
---|
721 | printf( "-" );
|
---|
722 | adrput( p->n_left );
|
---|
723 | }
|
---|
724 | tbl */
|
---|
725 | #ifdef notyet
|
---|
726 | printf("%c(%s)%c", (p->n_left->n_op==INCR ? '\0' : '-'),
|
---|
727 | rnames[p->n_left->n_left->n_rval],
|
---|
728 | (p->n_left->n_op==INCR ? '+' : '\0') );
|
---|
729 | #else
|
---|
730 | printf("%c(%s)%c", '-',
|
---|
731 | rnames[p->n_left->n_left->n_rval],
|
---|
732 | '\0' );
|
---|
733 | #endif
|
---|
734 | p->n_op = OREG;
|
---|
735 | p->n_rval = p->n_left->n_left->n_rval;
|
---|
736 | q = p->n_left;
|
---|
737 | #ifdef notyet
|
---|
738 |
|
---|
739 | p->n_lval = (p->n_left->n_op == INCR ? -p->n_left->n_right->n_lval : 0);
|
---|
740 | #else
|
---|
741 | p->n_lval = 0;
|
---|
742 | #endif
|
---|
743 | p->n_name[0] = '\0';
|
---|
744 | tfree(q);
|
---|
745 | }
|
---|
746 | return;
|
---|
747 |
|
---|
748 | default:
|
---|
749 | cerror( "illegal address" );
|
---|
750 | return;
|
---|
751 | }
|
---|
752 |
|
---|
753 | }
|
---|
754 |
|
---|
755 | /*
|
---|
756 | * print out a constant
|
---|
757 | */
|
---|
758 | void
|
---|
759 | acon(NODE *p)
|
---|
760 | {
|
---|
761 |
|
---|
762 | if (p->n_name[0] == '\0') {
|
---|
763 | printf(CONFMT, p->n_lval);
|
---|
764 | } else if( p->n_lval == 0 ) {
|
---|
765 | printf("%s", p->n_name);
|
---|
766 | } else {
|
---|
767 | printf("%s+", p->n_name);
|
---|
768 | printf(CONFMT, p->n_lval);
|
---|
769 | }
|
---|
770 | }
|
---|
771 |
|
---|
772 | #if 0
|
---|
773 | genscall( p, cookie ) register NODE *p; {
|
---|
774 | /* structure valued call */
|
---|
775 | return( gencall( p, cookie ) );
|
---|
776 | }
|
---|
777 |
|
---|
778 | /* tbl */
|
---|
779 | int gc_numbytes;
|
---|
780 | /* tbl */
|
---|
781 |
|
---|
782 | gencall( p, cookie ) register NODE *p; {
|
---|
783 | /* generate the call given by p */
|
---|
784 | register NODE *p1, *ptemp;
|
---|
785 | register temp, temp1;
|
---|
786 | register m;
|
---|
787 |
|
---|
788 | if( p->right ) temp = argsize( p->right );
|
---|
789 | else temp = 0;
|
---|
790 |
|
---|
791 | if( p->op == STCALL || p->op == UNARY STCALL ){
|
---|
792 | /* set aside room for structure return */
|
---|
793 |
|
---|
794 | if( p->stsize > temp ) temp1 = p->stsize;
|
---|
795 | else temp1 = temp;
|
---|
796 | }
|
---|
797 |
|
---|
798 | if( temp > maxargs ) maxargs = temp;
|
---|
799 | SETOFF(temp1,4);
|
---|
800 |
|
---|
801 | if( p->right ){ /* make temp node, put offset in, and generate args */
|
---|
802 | ptemp = talloc();
|
---|
803 | ptemp->op = OREG;
|
---|
804 | ptemp->lval = -1;
|
---|
805 | ptemp->rval = SP;
|
---|
806 | ptemp->name[0] = '\0';
|
---|
807 | ptemp->rall = NOPREF;
|
---|
808 | ptemp->su = 0;
|
---|
809 | genargs( p->right, ptemp );
|
---|
810 | nfree(ptemp);
|
---|
811 | }
|
---|
812 |
|
---|
813 | p1 = p->left;
|
---|
814 | if( p1->op != ICON ){
|
---|
815 | if( p1->op != REG ){
|
---|
816 | if( p1->op != OREG || R2TEST(p1->rval) ){
|
---|
817 | if( p1->op != NAME ){
|
---|
818 | order( p1, INAREG );
|
---|
819 | }
|
---|
820 | }
|
---|
821 | }
|
---|
822 | }
|
---|
823 |
|
---|
824 | /*
|
---|
825 | if( p1->op == REG && p->rval == R5 ){
|
---|
826 | cerror( "call register overwrite" );
|
---|
827 | }
|
---|
828 | */
|
---|
829 | /* tbl
|
---|
830 | setup gc_numbytes so reference to ZC works */
|
---|
831 |
|
---|
832 | gc_numbytes = temp;
|
---|
833 | /* tbl */
|
---|
834 |
|
---|
835 | p->op = UNARY CALL;
|
---|
836 | m = match( p, INTAREG|INTBREG );
|
---|
837 | /* tbl
|
---|
838 | switch( temp ) {
|
---|
839 | case 0:
|
---|
840 | break;
|
---|
841 | case 2:
|
---|
842 | printf( " tst (sp)+\n" );
|
---|
843 | break;
|
---|
844 | case 4:
|
---|
845 | printf( " cmp (sp)+,(sp)+\n" );
|
---|
846 | break;
|
---|
847 | default:
|
---|
848 | printf( " add $%d,sp\n", temp);
|
---|
849 | }
|
---|
850 | tbl */
|
---|
851 | return(m != MDONE);
|
---|
852 | }
|
---|
853 | #endif
|
---|
854 |
|
---|
855 | static char *
|
---|
856 | ccbranches[] = {
|
---|
857 | "jeql",
|
---|
858 | "jneq",
|
---|
859 | "jleq",
|
---|
860 | "jlss",
|
---|
861 | "jgeq",
|
---|
862 | "jgtr",
|
---|
863 | "jlequ",
|
---|
864 | "jlssu",
|
---|
865 | "jgequ",
|
---|
866 | "jgtru",
|
---|
867 | };
|
---|
868 |
|
---|
869 | /*
|
---|
870 | * printf conditional and unconditional branches
|
---|
871 | */
|
---|
872 | void
|
---|
873 | cbgen(int o, int lab)
|
---|
874 | {
|
---|
875 |
|
---|
876 | if (o == 0) {
|
---|
877 | printf(" jbr " LABFMT "\n", lab);
|
---|
878 | } else {
|
---|
879 | if (o > UGT)
|
---|
880 | comperr("bad conditional branch: %s", opst[o]);
|
---|
881 | printf("\t%s\t" LABFMT "\n", ccbranches[o-EQ], lab);
|
---|
882 | }
|
---|
883 | }
|
---|
884 |
|
---|
885 | static void
|
---|
886 | optim2(NODE *p, void *arg)
|
---|
887 | {
|
---|
888 | /* do local tree transformations and optimizations */
|
---|
889 |
|
---|
890 | register NODE *r;
|
---|
891 |
|
---|
892 | switch( p->n_op ) {
|
---|
893 |
|
---|
894 | case AND:
|
---|
895 | /* commute L and R to eliminate compliments and constants */
|
---|
896 | if( (p->n_left->n_op==ICON&&p->n_left->n_name[0]==0) || p->n_left->n_op==COMPL ) {
|
---|
897 | r = p->n_left;
|
---|
898 | p->n_left = p->n_right;
|
---|
899 | p->n_right = r;
|
---|
900 | }
|
---|
901 | #if 0
|
---|
902 | case ASG AND:
|
---|
903 | /* change meaning of AND to ~R&L - bic on pdp11 */
|
---|
904 | r = p->n_right;
|
---|
905 | if( r->op==ICON && r->name[0]==0 ) { /* compliment constant */
|
---|
906 | r->lval = ~r->lval;
|
---|
907 | }
|
---|
908 | else if( r->op==COMPL ) { /* ~~A => A */
|
---|
909 | r->op = FREE;
|
---|
910 | p->right = r->left;
|
---|
911 | }
|
---|
912 | else { /* insert complement node */
|
---|
913 | p->right = talloc();
|
---|
914 | p->right->op = COMPL;
|
---|
915 | p->right->rall = NOPREF;
|
---|
916 | p->right->type = r->type;
|
---|
917 | p->right->left = r;
|
---|
918 | p->right->right = NULL;
|
---|
919 | }
|
---|
920 | break;
|
---|
921 | #endif
|
---|
922 | }
|
---|
923 | }
|
---|
924 |
|
---|
925 | void
|
---|
926 | myreader(struct interpass *ipole)
|
---|
927 | {
|
---|
928 | struct interpass *ip;
|
---|
929 |
|
---|
930 | DLIST_FOREACH(ip, ipole, qelem) {
|
---|
931 | if (ip->type != IP_NODE)
|
---|
932 | continue;
|
---|
933 | walkf(ip->ip_node, optim2, 0);
|
---|
934 | }
|
---|
935 | }
|
---|
936 |
|
---|
937 | void
|
---|
938 | mycanon(NODE *p)
|
---|
939 | {
|
---|
940 | }
|
---|
941 |
|
---|
942 | void
|
---|
943 | myoptim(struct interpass *ip)
|
---|
944 | {
|
---|
945 | }
|
---|
946 |
|
---|
947 | /*
|
---|
948 | * Return argument size in regs.
|
---|
949 | */
|
---|
950 | static int
|
---|
951 | argsiz(NODE *p)
|
---|
952 | {
|
---|
953 | TWORD t = p->n_type;
|
---|
954 |
|
---|
955 | if (t == STRTY || t == UNIONTY)
|
---|
956 | return p->n_stsize/(SZINT/SZCHAR);
|
---|
957 | return szty(t);
|
---|
958 | }
|
---|
959 |
|
---|
960 | /*
|
---|
961 | * Last chance to do something before calling a function.
|
---|
962 | */
|
---|
963 | void
|
---|
964 | lastcall(NODE *p)
|
---|
965 | {
|
---|
966 | NODE *op = p;
|
---|
967 | int size = 0;
|
---|
968 |
|
---|
969 | /* Calculate argument sizes */
|
---|
970 | p->n_qual = 0;
|
---|
971 | if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
|
---|
972 | return;
|
---|
973 | for (p = p->n_right; p->n_op == CM; p = p->n_left)
|
---|
974 | size += argsiz(p->n_right);
|
---|
975 | size += argsiz(p);
|
---|
976 | op->n_qual = size; /* XXX */
|
---|
977 | }
|
---|
978 |
|
---|
979 | /*
|
---|
980 | * Return a class suitable for a specific type.
|
---|
981 | */
|
---|
982 | int
|
---|
983 | gclass(TWORD t)
|
---|
984 | {
|
---|
985 | return (szty(t) == 2 ? CLASSB : CLASSA);
|
---|
986 | }
|
---|
987 |
|
---|
988 | /*
|
---|
989 | * For class c, find worst-case displacement of the number of
|
---|
990 | * registers in the array r[] indexed by class.
|
---|
991 | */
|
---|
992 | int
|
---|
993 | COLORMAP(int c, int *r)
|
---|
994 | {
|
---|
995 | int num;
|
---|
996 |
|
---|
997 | switch (c) {
|
---|
998 | case CLASSA:
|
---|
999 | /* there are 12 classa, so min 6 classb are needed to block */
|
---|
1000 | num = r[CLASSB] * 2;
|
---|
1001 | num += r[CLASSA];
|
---|
1002 | return num < 12;
|
---|
1003 | case CLASSB:
|
---|
1004 | /* 6 classa may block all classb */
|
---|
1005 | num = r[CLASSB] + r[CLASSA];
|
---|
1006 | return num < 6;
|
---|
1007 | }
|
---|
1008 | comperr("COLORMAP");
|
---|
1009 | return 0; /* XXX gcc */
|
---|
1010 | }
|
---|
1011 |
|
---|
1012 | /*
|
---|
1013 | * Special shapes.
|
---|
1014 | */
|
---|
1015 | int
|
---|
1016 | special(NODE *p, int shape)
|
---|
1017 | {
|
---|
1018 | return SRNOPE;
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | /*
|
---|
1022 | * Target-dependent command-line options.
|
---|
1023 | */
|
---|
1024 | void
|
---|
1025 | mflags(char *str)
|
---|
1026 | {
|
---|
1027 | }
|
---|
1028 | /*
|
---|
1029 | * Do something target-dependent for xasm arguments.
|
---|
1030 | * Supposed to find target-specific constraints and rewrite them.
|
---|
1031 | */
|
---|
1032 | int
|
---|
1033 | myxasm(struct interpass *ip, NODE *p)
|
---|
1034 | {
|
---|
1035 | return 0;
|
---|
1036 | }
|
---|