📄 c21.c
字号:
#ifndef lintstatic char *sccsid = "@(#)c21.c 4.1 ULTRIX 7/3/90";#endif lint/************************************************************************ * * * Copyright (c) 1984-1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * * * 0008 Jon Reeves, 01-Mar-1989 * * Change dest() to invalidate wild stores sooner; fixed * * bypass of test when it immediately followed a store to -n(fp) * * (Change from 4.3 code.) * * * * 0007 David L Ballenger, 10-Jun-1986 * * Fix bug in redunbr() which didn't completely update the label * * information when changing a branch to go to a new label. * * This could cause the branch to go to an undefined label. * * * * 0006 David L Ballenger, 02-Mar-1986 * * Do further corrections on the bitopt() routine fixed previously * * do correctly distinguish when bixx operations can be optimized. * * The previous fix introduced problems with index mode. * * * * 0005 David L Ballenger, 24-Feb-1986 * * Fix problem reported by SPR ICA-679 in which a bitb was * * incorrectly being converted to jlbc. Also fix problem * * found in the QVSS driver in which a jbs/jbc was incorrectly * * converted into a jbss/jbcc. * * * * David L. Ballenger, 06-Nov-1984 * * 0004 Modify byondrd() to handle MFPR instructions correctly, i.e. * * to recognize that it is a 2 operand instruction. * * * * David L. Ballenger, 10-Oct-1984 * * 0003 Modify compat() so that GFLOAT, HFLOAT, and OCTA types are * * handled correctly, specifically so that GFLOAT and FFLOAT are * * correctly determined to be different types. * * * * David L. Ballenger, 19-Jul-1984 * * 0002 Fix problems in bicopt with optimizing BICL and preceding * * instructions. * * - don't allow a CVT of a float type preceding a BICL to be * * deleted. * * - don't allow a CVT or MOVZ with an auto(in|de)cremented source * * to be delete unless the source of the instruction replacing * * it is the same size. * * - don't replace a BICL with an EXTZV unless a preceding ASHL * * and/or CVT/MOVZ was deleted. * * * * David L. Ballenger, 24-May-1984 * * 0001 Fix problems with converting EXT[Z]V instructions to CVT{B|W}L * * or MOVZ{B|W}L instructions. An extract with a bit offset of 16 * * and length 16 was not being converted with the proper alignment.* * Also an extract with an offset of 8 and length 16 was not being * * converted at all. * * * ************************************************************************//* * C object code improver-- second part */#include "c2.h"#include <stdio.h>#include <ctype.h>#include <varargs.h>#include <strings.h>#define NUSE 6#define BITS_PER_UNIT 8 /* The bits per addressable unit is used to * calculate the addressable unit offset * for converting EXT instructions to CVT * or MOVZ instructions. 0001 */int ioflag;int biti[NUSE] = {1,2,4,8,16,32};int bitsize[] = { /* index by type codes */ 0, /* 0 not allocated */ 8, /* 1 BYTE */ 16, /* 2 WORD */ 32, /* 3 LONG */ 32, /* 4 FFLOAT */ 64, /* 5 DFLOAT */ 64, /* 6 QUAD */ 0, /* 7 OP2 */ 0, /* 8 OP3 */ 0, /* 9 OPB */ 0, /* 10 OPX */ 64, /* 11 GFLOAT */ 128, /* 12 HFLOAT */ 128 /* 13 OCTA */};int pos,siz; long f; /* for bit field communication */struct node *uses[NUSE]; /* for backwards flow analysis */char *lastrand; /* last operand of instruction */struct node *bflow();struct node *bicopt();char *findcon();/* new_operands * * Routine to reformat the new operands when an instruction or instruction * sequence is optimized. Accepts a variable list of 2 or more arguments. * The first argument is the pointer to the node which is getting the new * operands, the second argument is the format string and the rest of the * arguments are as specified in the format string as in printf(). * */static voidnew_operands(va_alist) va_dcl{ va_list args; register struct node *ptr; char *format; char operands[C2_ASIZE]; register int n_chars; va_start(args); /* * Get the node pointer and format, then call vsprintf() with * the format and the remaining arguments. */ ptr = va_arg(args,struct node *); format = va_arg(args,char *); n_chars = vsprintf(operands,format,args); if (n_chars > C2_ASIZE) { fputs("c2: buffer overflow in new_operands()\n",stderr); exit(1); } /* Allocate a buffer for the string, copy the new operands to it * and return a pointer to it. */ ptr->code = alloc(n_chars+1); (void)strcpy(ptr->code,operands);}redun3(p,split) register struct node *p; int split; {/* check for 3 addr instr which should be 2 addr */ if (OP3==((p->subop>>4)&0xF)) { if (split) splitrand(p); if (equstr(regs[RT1],regs[RT3]) && (p->op==ADD || p->op==MUL || p->op==BIS || p->op==XOR)) { register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; } if (equstr(regs[RT2],regs[RT3])) { p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; lastrand=regs[RT2]; *regs[RT3]=0; return(1); } } return(0);}bmove() { register struct node *p, *lastp; register char *cp1,*cp2; register int r; refcount(); for (p=lastp= &first; 0!=(p=p->forw); lastp=p); clearreg(); clearuse(); for (p=lastp; p!= &first; p=p->back) { if (debug) { printf("Uses:\n"); for (r=NUSE;--r>=0;) if (uses[r]) printf("%d: %s\n",r,uses[r]->code? uses[r]->code:""); printf("-\n"); } r=(p->subop>>4)&0xF; if (OP2==r && (cp1=p->code, *cp1++)=='$' && *cp1++=='0' && *cp1++==',' && !source(cp1)) {/* a no-op unless MUL or DIV */ if (p->op==MUL) {p->op=MOV; p->subop&=0xF; p->pop=0;} else if (p->op==DIV) fprintf(stderr,"c2: zero divide\n"); else {delnode(p); redunm++; continue;} } if (OP3==r && 0!=redun3(p,1)) {newcode(p); redunm++;} switch (p->op) { case LABEL: case DLABEL: for (r=NUSE; --r>=0;) if (uses[r]) p->ref=(struct node *) (((int)p->ref)|biti[r]); break; case CALLS: clearuse(); goto std; case 0: clearuse(); break; case SUB: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; if (*cp1++!='$') goto std; splitrand(p); if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ char buf[C2_ASIZE]; cp2=buf; *cp2++='-'; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; cp1="(fp),"; while (*cp2++= *cp1++); --cp2; cp1=regs[RT3]; while (*cp2++= *cp1++); p->code=copy(buf); p->combop=T(MOVA,LONG); p->pop=0; } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; } goto std; case ADD: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; if (*cp1++!='$') goto std; splitrand(p); if (isstatic(cp1) && (r=isreg(regs[RT2]))>=0 && r<NUSE && uses[r]==p->forw) { /* address comp: ** addl2 $_foo,r0 \ movab _foo[r0],bar ** movl r0,bar / */ register struct node *pnext = p->forw; char buf[C2_ASIZE]; if (pnext->op == MOV && pnext->subop == LONG) { cp1 = ®s[RT1][1]; cp2 = &buf[0]; while (*cp2++ = *cp1++) ; cp2--; splitrand(pnext); if (r == isreg(regs[RT1])) { delnode(p); p = pnext; p->op = MOVA; p->subop = BYTE; p->pop = 0; cp1 = regs[RT1]; *cp2++ = '['; while (*cp2++ = *cp1++) ; cp2--; *cp2++ = ']'; *cp2++ = ','; cp1 = regs[RT2]; while (*cp2++ = *cp1++) ; p->code = copy(buf); } } } else if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; p->combop=T(MOVA,LONG); p->pop=0; } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) { p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; } /* fall thru ... */ case CASE: default: std: p=bflow(p); break; case MUL: { /* ** Change multiplication by constant powers of 2 to ** shifts. */ splitrand(p); if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; if ((r = ispow2(getnum(®s[RT1][1]))) < 0) goto std; switch (r) { case 0: /* mull3 $1,x,y */ if (p->subop == U(LONG,OP3)) { if (equstr(regs[RT2], regs[RT3])) { delnode(p); p = p->forw; } else { p->op = MOV; p->subop = LONG; p->pop = 0; newcode(p); nchange++; } } else if (p->subop == U(LONG,OP2)) { delnode(p); p = p->forw; } goto std; case 1: /* mull2 $2,x */ if (p->subop == U(LONG, OP2) && !source(regs[RT2])) { strcpy(regs[RT1], regs[RT2]); p->op = ADD; p->pop = 0; newcode(p); nchange++; } goto std; } if(p->subop==U(LONG,OP3)||(p->subop==U(LONG,OP2)&&!source(regs[RT2]))) { if (p->subop == U(LONG,OP2)) strcpy(regs[RT3], regs[RT2]); sprintf(regs[RT1], "$%d", r); p->op = ASH; p->subop = LONG; p->pop = 0; newcode(p); nchange++; } goto std; } case ASH: { /* address comp: ** ashl $1,bar,r0 \ movl bar,r0 ** movab _foo[r0] / movaw _foo[r0] ** ** ashl $2,r0,r0 \ moval _foo[r0] ** movab _foo[r0] / */ register struct node *pf; register int shfrom, shto; long shcnt; char *regfrom; splitrand(p); if (regs[RT1][0] != '$') goto std; if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 3) goto std; if ((shfrom = isreg(regs[RT2])) >= 0) regfrom = copy(regs[RT2],"]"); if ((shto = isreg(regs[RT3])) >= 0 && shto<NUSE) { int regnum; if (uses[shto] != (pf = p->forw)) goto ashadd; if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; if (pf->subop != BYTE) goto ashadd; splitrand(pf); if (!indexa(regs[RT1])) goto std; cp2 = regs[RT1]; if(!isstatic(cp2)) goto std; while (*cp2++ != '[') ; if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; regnum = *cp2++ - '0'; if (isdigit(*cp2)) { if (cp2[1] != ']') goto std; regnum *= 10; regnum += *cp2 - '0'; } if (regnum != shto) goto std; if (shfrom >= 0) /* ashl $N,r*,r0 */ { delnode(p); if (shfrom != shto) { uses[shto] = NULL; splitrand(pf); cp2=regs[RT1]; while (*cp2++!='['); cp1=regfrom; while (*cp2++= *cp1++); newcode(pf); } } else { p->op = MOV; splitrand(p); strcpy(regs[RT1], regs[RT2]); strcpy(regs[RT2], regs[RT3]); regs[RT3][0] = '\0'; p->pop = 0; newcode(p); } switch (shcnt) { case 1: pf->subop = WORD; break; case 2: pf->subop = LONG; break; case 3: pf->subop = QUAD; break; } redunm++; nsaddr++; nchange++; } goto std;ashadd: /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ if (shcnt == 1 && equstr(regs[RT2], regs[RT3])) { /* ** quickie: ** ashl $1,A,A > addl2 A,A */ p->op = ADD; p->subop = U(LONG,OP2); p->pop = 0; strcpy(regs[RT1], regs[RT2]); regs[RT3][0] = '\0'; newcode(p); nchange++; } goto std; } case EXTV: case EXTZV: { /* bit tests: ** extv A,$1,B,rC \ ** tstl rC > jbc A,B,D ** jeql D / ** ** also byte- and word-size fields: ** extv $n*8,$8,A,B > cvtbl n+A,B ** extv $n*16,$16,A,B > cvtwl n+A,B ** extzv $n*8,$8,A,B > movzbl n+A,B ** extzv $n*16,$16,A,B > movzwl n+A,B */ register struct node *pf; /* forward node */ register struct node *pn; /* next node (after pf) */ int flen; /* field length */ splitrand(p); if (regs[RT2][0] != '$') goto std; if ((flen = getnum(®s[RT2][1])) < 0) goto std; if (flen == 1) { register int extreg; /* reg extracted to */ extreg = isreg(regs[RT4]); if (extreg < 0 || extreg >= NUSE) goto std; if ((pf = p->forw)->op != TST) goto std; if (uses[extreg] && uses[extreg] != pf) goto std; splitrand(pf); if (extreg != isreg(regs[RT1])) goto std; if ((pn = pf->forw)->op != CBR) goto std; if (pn->subop != JEQ && pn->subop != JNE) goto std; delnode(p); delnode(pf); pn->subop = (pn->subop == JEQ) ? JBC : JBS; for(cp2=p->code; *cp2++!=',';); for(cp1=cp2; *cp1++!=',';); while (*cp1!=',') *cp2++= *cp1++; *cp2='\0'; pn->code = p->code; pn->pop = NULL; uses[extreg] = NULL; } else if (flen == 8 || flen == 16) { /* If the extract is a byte or word length we may be * able to change it to a CVT or MOVZ instruction. */ register int boff; /* bit offset */ register int coff; /* chunk (byte or word) offset*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -