126440Ssam #ifndef lint 2*33361Sdonn static char sccsid[] = "@(#)c21.c 1.7 (Berkeley/CCI) 01/15/88"; 326440Ssam #endif 426440Ssam 526440Ssam /* 626440Ssam * C object code improver-- second part 726440Ssam */ 826440Ssam 926440Ssam #include "c2.h" 1026440Ssam #include <stdio.h> 1126440Ssam #include <ctype.h> 1226440Ssam 1326440Ssam int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */ 1426440Ssam 1526440Ssam redun3(p) register struct node *p; { 1626440Ssam /* check for 3 addr instr which should be 2 addr */ 1729775Ssam if (has3ops(p)) { 1826440Ssam if (equstr(regs[RT1],regs[RT3]) 1926440Ssam && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) { 2026440Ssam register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; 2126440Ssam } 2226440Ssam if (equstr(regs[RT2],regs[RT3])) { 2326440Ssam p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; 2426440Ssam lastrand=regs[RT2]; *regs[RT3]=0; return(1); 2526440Ssam } 2626440Ssam } return(0); 2726440Ssam } 2826440Ssam 2926440Ssam bmove() { 3026440Ssam register struct node *p, *lastp; register char *cp1,*cp2; register int r; 3126440Ssam struct node *flops(); 3226440Ssam 3326440Ssam refcount(); 3426440Ssam for (p=lastp= &first; 0!=(p=p->forw); lastp=p); 3526440Ssam clearreg(); clearuse(); 3626440Ssam for (p=lastp; p!= &first; p=p->back) { 3726440Ssam if (debug) { 3826440Ssam printf("Uses: "); 3926440Ssam if (useacc) 4026440Ssam printf("acc: %s\n",useacc->code? useacc->code:""); 4126440Ssam for (r=NUSE;--r>=0;) if (uses[r]) 4226440Ssam printf("%d: %s\n",r,uses[r]->code? uses[r]->code:""); 4326440Ssam printf("-\n"); 4426440Ssam } 4526440Ssam r=(p->subop>>4)&0xF; 4626440Ssam splitrand(p); 4726440Ssam if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;} 4826440Ssam /* ops that do nothing */ 4926440Ssam if(p->op==MOV && equstr(regs[RT1], regs[RT2])) 5026440Ssam if(p->forw->op!=CBR) { 5126440Ssam delnode(p); redunm++; continue; 5226440Ssam } else { 5326440Ssam p->op=TST; p->pop=0; 5426440Ssam while(*p->code++ != ','); 5526440Ssam redunm++; 5626440Ssam } 5726440Ssam else if((cp1=p->code, *cp1++)=='$' && 5826440Ssam (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') { 5929775Ssam switch((p->code[1]<<8)|ord(p->op)) { 6029775Ssam case (('0'<<8)|ord(ADD)): 6129775Ssam case (('0'<<8)|ord(SUB)): 6229775Ssam case (('-'<<8)|ord(AND)): 6329775Ssam case (('0'<<8)|ord(OR)): 6429775Ssam case (('0'<<8)|ord(XOR)): 6529775Ssam case (('1'<<8)|ord(MUL)): 6629775Ssam case (('1'<<8)|ord(DIV)): 6729775Ssam case (('0'<<8)|ord(SHAL)): 6829775Ssam case (('0'<<8)|ord(SHAR)): 6929775Ssam case (('0'<<8)|ord(SHL)): 7029775Ssam case (('0'<<8)|ord(SHR)): 7126440Ssam if(r == OP2) { 7226440Ssam if(p->forw->op!=CBR) { 7326440Ssam delnode(p); redunm++; continue; 7426440Ssam } else { 7526440Ssam p->op=TST; p->subop&=0xF; p->pop=0; 7626440Ssam while(*p->code++ != ','); 7726440Ssam redunm++; 7826440Ssam } 7926440Ssam } else { /* OP3 or shift */ 8026440Ssam p->op=MOV; p->subop&=0xF; p->pop=0; 8126440Ssam while(*p->code++ != ','); 8226440Ssam p = p->forw; redunm++; continue; 8326440Ssam } 8426440Ssam break; 8529775Ssam case (('0'<<8)|ord(MUL)): 8629775Ssam case (('0'<<8)|ord(AND)): 8726440Ssam p->op=CLR; p->subop&=0xF; p->pop=0; 8826440Ssam while(*p->code++ != ','); 8926440Ssam if(r == OP3) 9026440Ssam while(*p->code++ != ','); 9126440Ssam redunm++; 9226440Ssam } 9326440Ssam } 9426440Ssam switch (p->op) { 9526440Ssam case LABEL: case DLABEL: 9626440Ssam for (r=NUSE; --r>=0;) 9726440Ssam if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r)); 9826440Ssam if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE)); 9926440Ssam break; 10026440Ssam case CALLS: 10126440Ssam case CALLF: 10226440Ssam clearuse(); goto std; 10329775Ssam case NIL: 10426440Ssam clearuse(); break; 10526440Ssam case CVT: 10626440Ssam { long n; 10726440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 10826440Ssam if (*cp1++!='$') goto std; splitrand(p); 10926440Ssam n = getnum(®s[RT1][1]); 11026440Ssam if(r==BYTE && (n<-128 || n>127)) goto std; 11126440Ssam if(r==WORD && (n<-32768 || n>32767)) goto std; 11226440Ssam p->op = MOV; p->subop = r; p->pop = 0; 11326440Ssam } goto std; 11426440Ssam 11526440Ssam case SUB: 11626440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 11726440Ssam if (*cp1++!='$') goto std; splitrand(p); 11826440Ssam #ifdef MOVAFASTER 11926440Ssam if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ 12026440Ssam char buf[C2_ASIZE]; cp2=buf; *cp2++='-'; 12126440Ssam cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; 12226440Ssam cp1="(fp),"; while (*cp2++= *cp1++); --cp2; 12326440Ssam cp1=regs[RT3]; while (*cp2++= *cp1++); 12426440Ssam p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0; 12526440Ssam } else 12626440Ssam #endif MOVAFASTER 12729670Ssam if (*cp1++=='-' && 0==(r=getnum(cp1)) && 12829670Ssam !checkexpr(cp1)) { 12926440Ssam p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; 13026440Ssam } goto std; 13126440Ssam case ADD: 13226440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 13326440Ssam if (*cp1++!='$') goto std; splitrand(p); 13429775Ssam if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw) 13526440Ssam { 13626440Ssam /* address comp: 13726440Ssam ** addl2 $_foo,r0 \ movab _foo[r0],bar 13826440Ssam ** movl r0,bar / 13926440Ssam */ 14026440Ssam register struct node *pnext = p->forw; 14126440Ssam char buf[C2_ASIZE]; 14226440Ssam 14326440Ssam if (pnext->op == MOV && pnext->subop == LONG) 14426440Ssam { 14526440Ssam cp1 = ®s[RT1][1]; cp2 = &buf[0]; 14626440Ssam while (*cp2++ = *cp1++) ; cp2--; 14726440Ssam splitrand(pnext); 14826440Ssam if (r == isreg(regs[RT1])) 14926440Ssam { 15026440Ssam delnode(p); p = pnext; 15126440Ssam p->op = MOVA; p->subop = BYTE; 15226440Ssam p->pop = 0; 15326440Ssam cp1 = regs[RT1]; *cp2++ = '['; 15426440Ssam while (*cp2++ = *cp1++) ; cp2--; 15526440Ssam *cp2++ = ']'; *cp2++ = ','; 15626440Ssam cp1 = regs[RT2]; 15726440Ssam while (*cp2++ = *cp1++) ; 15826440Ssam p->code = copy(buf); 15926440Ssam } 16026440Ssam } 16126440Ssam } 16226440Ssam else 16326440Ssam #ifdef MOVAFASTER 16426440Ssam if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ 16526440Ssam cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; 16626440Ssam cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; 16726440Ssam p->op = MOVA; p->subop = BYTE; p->pop=0; 16826440Ssam } else 16926440Ssam #endif MOVAFASTER 17029670Ssam if (*cp1++=='-' && 0==(r=getnum(cp1)) && 17129670Ssam !checkexpr(cp1)) { 17226440Ssam p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; 17326440Ssam } 17426440Ssam /* fall thru ... */ 17526440Ssam case CASE: 17626440Ssam default: std: 17726440Ssam p=bflow(p); break; 17826440Ssam 17926440Ssam case MUL: 18026440Ssam /* 18126440Ssam ** Change multiplication 18226440Ssam ** by constant powers of 2 to shifts. 18326440Ssam */ 18426440Ssam splitrand(p); 18526440Ssam if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; 18626440Ssam if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std; 18726440Ssam /* mull2 $2,x */ 18826440Ssam if(r == 1 && p->subop == U(LONG, OP2)) { 18926440Ssam strcpy(regs[RT1], regs[RT2]); 19026440Ssam p->op = ADD; p->pop = 0; newcode(p); 19126440Ssam goto std; 19226440Ssam } 19326440Ssam if (p->subop == U(LONG,OP2)) 19426440Ssam strcpy(regs[RT3], regs[RT2]); 19526440Ssam sprintf(regs[RT1], "$%d", r); 19626440Ssam p->op = SHL; p->subop = LONG; 19726440Ssam p->pop = 0; newcode(p); 19826440Ssam goto std; 19926440Ssam 20026440Ssam case SHAL: 20126440Ssam case SHL: 20226440Ssam { 20326440Ssam /* bit tests: 20426440Ssam ** shll A,$1,rC \ 20526440Ssam ** bitl B,rC > jbc A,B,D 20626440Ssam ** jeql D / 20726440Ssam ** 20826440Ssam ** address comp: 20926440Ssam ** shll $1,bar,r0 \ movl bar,r0 21026440Ssam ** movab _foo[r0] / movaw _foo[r0] 21126440Ssam ** 21226440Ssam ** shll $2,r0,r0 \ moval _foo[r0] 21326440Ssam ** movab _foo[r0] / 21426440Ssam */ 21526440Ssam register struct node *pf; 21626440Ssam register struct node *pn; 21726440Ssam register int shfrom, shto; 21826440Ssam long shcnt; 21926440Ssam char *regfrom; 22026440Ssam 22126440Ssam splitrand(p); 22226440Ssam if (regs[RT1][0] != '$') { 22326440Ssam if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 22426440Ssam if (regs[RT2][0] != '$') goto std; 22526440Ssam if (getnum(®s[RT2][1]) != 1) goto std; 22629775Ssam if (!tempreg(regs[RT3],r)) goto std; 22726440Ssam if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std; 22826440Ssam if (uses[r] && uses[r] != pf) goto std; 22926440Ssam splitrand(pf); 23026440Ssam if (r == isreg(regs[RT1])) cp2 = regs[RT2]; 23126440Ssam else if (r == isreg(regs[RT2])) cp2 = regs[RT1]; 23226440Ssam else goto std; 23326440Ssam if (*cp2 == '$') goto std; 23426440Ssam if ((pn = pf->forw)->op != CBR) goto std; 23526440Ssam if (pn->subop != JEQ && pn->subop != JNE) goto std; 23626440Ssam delnode(p); delnode(pf); 23726440Ssam pn->subop = (pn->subop == JEQ) ? JBC : JBS; 23826440Ssam for(cp1=p->code; *cp1++!=',';); 23926440Ssam while (*cp1++= *cp2++); 24026440Ssam pn->code = p->code; pn->pop = NULL; 24126440Ssam uses[r] = NULL; 24226440Ssam nbj++; 24326440Ssam p = pn; 24426440Ssam goto std; 24526440Ssam } 24626440Ssam if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std; 24726440Ssam if ((shfrom = isreg(regs[RT2])) >= 0) 24826440Ssam regfrom = copy(regs[RT2]); 24929775Ssam if (tempreg(regs[RT3],shto)) 25026440Ssam { 25126440Ssam int regnum; 25226440Ssam 25326440Ssam if (uses[shto] != (pf = p->forw)) goto ashadd; 25426440Ssam if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; 25526440Ssam if (pf->subop != BYTE) goto ashadd; 25626440Ssam splitrand(pf); 25726440Ssam if (!indexa(regs[RT1])) goto std; 25826440Ssam cp2 = regs[RT1]; 25926440Ssam if(!isstatic(cp2)) goto std; 26026440Ssam while (*cp2++ != '[') ; 26126440Ssam if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; 26226440Ssam regnum = *cp2++ - '0'; 26326440Ssam if (isdigit(*cp2)) 26426440Ssam { 26526440Ssam if (cp2[1] != ']') goto std; 26626440Ssam regnum *= 10; regnum += *cp2 - '0'; 26726440Ssam } 26826440Ssam if (regnum != shto) goto std; 26926440Ssam if (shfrom >= 0) /* shll $N,r*,r0 */ 27026440Ssam { 27126440Ssam delnode(p); 27226440Ssam p = pf; 27326440Ssam if (shfrom != shto) 27426440Ssam { 27526440Ssam uses[shto] = NULL; splitrand(pf); 27626440Ssam cp2=regs[RT1]; while (*cp2++!='['); 27726440Ssam cp1=regfrom; while (*cp2++= *cp1++); 27826440Ssam cp2[-1] = ']'; *cp2 = 0; 27926440Ssam newcode(pf); 28026440Ssam } 28126440Ssam } 28226440Ssam else 28326440Ssam { 28426440Ssam p->op = MOV; splitrand(p); 28526440Ssam strcpy(regs[RT1], regs[RT2]); 28626440Ssam strcpy(regs[RT2], regs[RT3]); 28726440Ssam regs[RT3][0] = '\0'; 28826440Ssam p->pop = 0; newcode(p); 28926440Ssam } 29026440Ssam switch (shcnt) 29126440Ssam { 29226440Ssam case 1: pf->subop = WORD; break; 29326440Ssam case 2: pf->subop = LONG; break; 29426440Ssam } 29526440Ssam redunm++; nsaddr++; 29626440Ssam } 29726440Ssam goto std; 29826440Ssam ashadd: 29926440Ssam /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ 30026440Ssam if (shcnt == 1) { 30126440Ssam /* 30226440Ssam ** quickie: 30326440Ssam ** shll $1,A,A > addl2 A,A 30426440Ssam ** shll $1,A,B > addl3 A,A,B 30526440Ssam */ 30626440Ssam p->op = ADD; 30726440Ssam strcpy(regs[RT1], regs[RT2]); 30826440Ssam if(equstr(regs[RT2], regs[RT3])) { 30926440Ssam p->subop = U(LONG,OP2); 31026440Ssam regs[RT3][0] = '\0'; 31126440Ssam } else 31226440Ssam p->subop = U(LONG,OP3); 31326440Ssam p->pop = 0; 31426440Ssam newcode(p); 31526440Ssam } 31626440Ssam goto std; 31726440Ssam } 31826440Ssam 31926440Ssam case SHAR: 32026440Ssam case SHR: 32126440Ssam { 32226440Ssam /* bit tests: 32326440Ssam ** shrl A,B,rC \ 32426440Ssam ** bitl $1,rC > jbc A,B,D 32526440Ssam ** jeql D / 32626440Ssam */ 32726440Ssam register struct node *pf; /* forward node */ 32826440Ssam register struct node *pn; /* next node (after pf) */ 32926440Ssam register int extreg; /* reg extracted to */ 33026440Ssam 33126440Ssam splitrand(p); 33226440Ssam if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 33329775Ssam if (!tempreg(regs[RT3],extreg)) goto std; 33426440Ssam if ((pf = p->forw)->op != BIT) goto std; 33526440Ssam if (uses[extreg] && uses[extreg] != pf) goto std; 33626440Ssam splitrand(pf); 33726440Ssam if (regs[RT1][0] != '$') goto std; 33826440Ssam if (getnum(®s[RT1][1]) != 1) goto std; 33926440Ssam if (extreg != isreg(regs[RT2])) goto std; 34026440Ssam if ((pn = pf->forw)->op != CBR) goto std; 34126440Ssam if (pn->subop != JEQ && pn->subop != JNE) goto std; 34226440Ssam delnode(p); delnode(pf); 34326440Ssam pn->subop = (pn->subop == JEQ) ? JBC : JBS; 34426440Ssam for(cp1=p->code; *cp1++!=',';); 34526440Ssam while (*cp1!=',') cp1++; *cp1='\0'; 34626440Ssam pn->code = p->code; pn->pop = NULL; 34726440Ssam uses[extreg] = NULL; nbj++; 34826440Ssam p = pn; 34926440Ssam goto std; 35026440Ssam } 35126440Ssam 35226440Ssam case AND: 35326440Ssam { 35426440Ssam /* unsigned conversion: 35526440Ssam ** cvtbl A,B; andl2 $255,B > movzbl A,B 35626440Ssam ** 35726440Ssam ** also byte- and word-size fields: 35826440Ssam ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B 35926440Ssam ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B 36026440Ssam */ 36126440Ssam char src[C2_ASIZE]; 36226440Ssam register int f; /* field length */ 36326440Ssam register struct node *pb = p->back; /* backward node */ 36426440Ssam 36526440Ssam if (p->subop != U(LONG,OP2)) 36626440Ssam goto std; 36726440Ssam splitrand(p); cp1=regs[RT1]; 36826440Ssam if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff) 36926440Ssam goto std; 37026440Ssam f = f==0xff ? 8 : 16; 37126440Ssam if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR) 37226440Ssam goto std; 37326440Ssam /* save source of ANDL in 'src' */ 37426440Ssam strcpy(src, regs[RT2]); 37526440Ssam splitrand(pb); 37626440Ssam if (!equstr(src,lastrand)) 37726440Ssam goto std; 37826440Ssam if (pb->op==CVT || pb->op==MOVZ) { 37926440Ssam if (!(bitsize[pb->subop&0xF]==f 38026440Ssam && bitsize[pb->subop>>4]>=f)) /* good CVT */ 38126440Ssam goto std; 38226440Ssam strcpy(src, regs[RT1]); 38326440Ssam } else { 38426440Ssam register int boff; /* bit offset */ 38526440Ssam 38626440Ssam if (regs[RT1][0] != '$') goto std; 38726440Ssam if ((boff = getnum(®s[RT1][1])) < 0) goto std; 38826440Ssam if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std; 38926440Ssam if ((boff & (f-1)) != 0) goto std; 39026440Ssam boff = (32-boff-f) / 8; 39126440Ssam if (boff == 0) 39226440Ssam strcpy(src, regs[RT2]); 39326440Ssam else 39426440Ssam sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+", 39526440Ssam regs[RT2]); 39626440Ssam } 39726440Ssam delnode(pb); 39826440Ssam p->op = MOVZ; 39926440Ssam p->subop = U((f==8 ? BYTE : WORD), LONG); 40026440Ssam sprintf(line,"%s,%s",src,lastrand); 40126440Ssam p->pop=0; 40226440Ssam p->code = copy(line); 40326440Ssam goto std; 40426440Ssam } 40526440Ssam 40626440Ssam case CMP: 40726440Ssam { 40826440Ssam /* comparison to -63 to -1: 40926440Ssam ** cmpl r0,$-1 > incl r0 41026440Ssam ** jeql ... 41126440Ssam ** 41226440Ssam ** cmpl r0,$-63 > addl2 $63,r0 41326440Ssam ** jeql ... 41426440Ssam */ 41526440Ssam register int num; 41626440Ssam register int reg; 41726440Ssam register struct node *regp = p->back; 41826440Ssam 41926440Ssam if (p->forw->op != CBR) goto std; 42026440Ssam if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; 42126440Ssam splitrand(p); 42226440Ssam if (strncmp(regs[RT2], "$-", 2) != 0) goto std; 42326440Ssam reg = r = isreg(regs[RT1]); 42426440Ssam if (r < 0) goto std; 42526440Ssam if (r < NUSE && uses[r] != 0) goto std; 42626440Ssam if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) 42726440Ssam { 42826440Ssam if (*regp->code != 'r') goto std; 42926440Ssam reg = regp->code[1] - '0'; 43026440Ssam if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) 43126440Ssam goto std; 43226440Ssam } 43326440Ssam if (r >= NUSE) goto std; 43426440Ssam if (reg != r) 43526440Ssam sprintf(regs[RT1], "r%d", reg); 43626440Ssam if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; 43726440Ssam if (num == 1) 43826440Ssam { 43926440Ssam p->op = INC; regs[RT2][0] = '\0'; 44026440Ssam } 44126440Ssam else 44226440Ssam { 44326440Ssam register char *t; 44426440Ssam 44526440Ssam t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; 44626440Ssam p->op = ADD; p->subop = U(p->subop, OP2); 44726440Ssam for (t = ®s[RT1][2]; t[-1] = *t; t++) ; 44826440Ssam } 44926440Ssam p->pop = 0; newcode(p); 45026440Ssam goto std; 45126440Ssam } 45226440Ssam 45326440Ssam case JBR: case JMP: 45426440Ssam clearuse(); 45526440Ssam if ((p->subop&0xF)==RET) { 45626440Ssam switch((p->subop>>4)&0xF) { 45726440Ssam case 2: uses[1]=p; regs[1][0]= -1; 45826440Ssam case 1: uses[0]=p; regs[0][0]= -1; 45926440Ssam } 46026440Ssam break; 46126440Ssam } 46226440Ssam if (p->ref==0) goto std; /* jmp (r0) */ 46326440Ssam /* fall through */ 46426440Ssam case CBR: 46526440Ssam if (p->ref->ref!=0) { 46626440Ssam for (r=NUSE;--r>=0;) 46726440Ssam if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} 46826440Ssam if ((1<<NUSE) & (int)p->ref->ref) useacc=p; 46926440Ssam } 47026440Ssam break; 47126440Ssam case LNF: 47226440Ssam /* lnf a; addf b ==> ldf b; subf a */ 47326440Ssam { register struct node *pf = p->forw; 47426440Ssam if(pf->op==ADDF && p->subop==pf->subop) { 47526440Ssam p->op = LDF; 47626440Ssam p->pop = 0; 47726440Ssam pf->op = SUBF; 47826440Ssam pf->pop = 0; 47926440Ssam cp1 = p->code; 48026440Ssam p->code = pf->code; 48126440Ssam pf->code = cp1; 48226440Ssam p = pf->forw; 48326440Ssam break; 48426440Ssam }} 48526440Ssam case LDF: case LDFD: case CVLF: /* destroy acc */ 48626440Ssam useacc = 0; 48726440Ssam goto std; 48826440Ssam case STF: 48926440Ssam { register struct node *pf; 49026440Ssam if((pf=flops(p)) != p) { 49126440Ssam p = pf; /* usually p->forw; */ 49226440Ssam break; 49326440Ssam }} 49426440Ssam if(ldmov(p)) { 49526440Ssam p = p->forw; 49626440Ssam break; 49726440Ssam } 49826440Ssam if(useacc == 0) 49926440Ssam useacc = p; 50026440Ssam goto std; 50126440Ssam case ADDF: case MULF: /* commutatives - create clients for flops */ 50226440Ssam /* stf a; ldf b; addf a => stf a; ldf a; addf b */ 50326440Ssam { register struct node *pb = p->back; 50426440Ssam register struct node *pbb = pb->back; 50526440Ssam if(pb->op==LDF && pb->subop==p->subop && 50626440Ssam pbb && pbb->op==STF && pbb->subop==p->subop && 50726440Ssam equstr(pbb->code, p->code)) { 50826440Ssam cp1 = p->code; 50926440Ssam p->code = pb->code; 51026440Ssam pb->code = cp1; 51126440Ssam }} 51226440Ssam /* use acc and regs */ 51326440Ssam case CMPF: case CVFL: case SUBF: case DIVF: 51426440Ssam if(useacc == 0) 51526440Ssam useacc = p; 51626440Ssam goto std; 51729670Ssam case TSTF: 51829670Ssam break; 51929670Ssam case PUSHD: 52026440Ssam if(ldmov(p)) { 52126440Ssam p = p->forw; 52226440Ssam break; 52326440Ssam } 52426440Ssam case CVDF: case NEGF: /* use only acc */ 52526440Ssam case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: 52626440Ssam if(useacc == 0) 52726440Ssam useacc = p; 52826440Ssam case EROU: case JSW: 52926440Ssam case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; 53026440Ssam } 53126440Ssam } 53226440Ssam for (p= &first; p!=0; p=p->forw) 53326440Ssam if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ 53426440Ssam } 53526440Ssam 53626440Ssam char * 53726440Ssam byondrd(p) register struct node *p; { 53826440Ssam /* return pointer to register which is "beyond last read/modify operand" */ 53929775Ssam if (has2ops(p)) return(regs[RT3]); 54026440Ssam switch (p->op) { 54126440Ssam case MFPR: 54226440Ssam case PUSHA: 54326440Ssam case TST: case INC: case DEC: case PUSH: 54426440Ssam case LDF: case LNF: case CVLF: case LDFD: 54526440Ssam case ADDF: case SUBF: case MULF: case DIVF: 54626440Ssam case CMPF: 54726440Ssam return(regs[RT2]); 54826440Ssam case MTPR: 54926440Ssam #ifndef EMOD 55026440Ssam case EDIV: 55126440Ssam #endif EMOD 55226440Ssam case CBR: /* must be JBC/JBS */ 55326440Ssam case BIT: case CMP: case CALLS: case CALLF: 55426440Ssam case CMPF2: 55526440Ssam return(regs[RT3]); 55626440Ssam case EMUL: 55726440Ssam case PROBE: 55826440Ssam case MOVBLK: 55926440Ssam case CASE: 56026440Ssam return(regs[RT4]); 56126440Ssam } 56226440Ssam return(lastrand); 56326440Ssam } 56426440Ssam 56526440Ssam struct node * 56626440Ssam bflow(p) 56729775Ssam register struct node *p; 56826440Ssam { 56926440Ssam register char *cp1,*cp2,**preg; 57026440Ssam register int r, fr, dblflg=0; 57126440Ssam int flow= -1; 57226440Ssam struct node *olduse=0, *olduse1=0; 57326440Ssam 574*33361Sdonn if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 || 575*33361Sdonn p->op==EMUL) 57626440Ssam dblflg |= 1; /* double dest */ 57729775Ssam if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) 57826440Ssam dblflg |= 2; /* double src */ 57926440Ssam splitrand(p); 58029775Ssam if (p->op!=PUSH && 58126440Ssam #ifndef EMOD 58229775Ssam p->op!=EDIV && 58326440Ssam #endif EMOD 58429775Ssam p->op!=EMUL && 58529775Ssam p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { 58629775Ssam if (equtype(p->subop,regs[r][0]) || 58729775Ssam ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && 58829775Ssam (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || 58929775Ssam p->op==MOVA && compat(LONG, regs[r][0])) { 59026440Ssam register int r2; 59129775Ssam 59229775Ssam if (regs[r][1]!=0) { /* send directly to destination */ 59326440Ssam if (p->op==INC || p->op==DEC) { 59429775Ssam p->op = (p->op==DEC) ? SUB : ADD; 59529775Ssam /* use 2 now, convert to 3 later */ 59629775Ssam p->subop=(OP2<<4)+(p->subop&0xF); 59726440Ssam p->pop=0; 59829775Ssam cp1=lastrand; cp2=regs[RT2]; 59929775Ssam while (*cp2++= *cp1++) /* copy reg */ 60029775Ssam ; 60126440Ssam cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; 60226440Ssam } 60326440Ssam cp1=regs[r]+1; cp2=lastrand; 60429775Ssam if (has2ops(p)) { 60529775Ssam /* use 3 operand form of instruction */ 60626440Ssam p->pop=0; 60729775Ssam p->subop += (OP3-OP2)<<4; 60829775Ssam lastrand = cp2 = regs[RT3]; 60926440Ssam } 61029775Ssam while (*cp2++= *cp1++) 61129775Ssam ; 61226440Ssam if (p->op==MOVA && p->forw->op==PUSH) { 61326440Ssam p->op=PUSHA; 61426440Ssam *regs[RT2]=0; p->pop=0; 61529775Ssam } else if ((p->op==MOV || p->op==CVT) && 61629775Ssam p->forw->op==PUSH) { 61726440Ssam p->op=PUSH; p->subop &= 0xF; 61826440Ssam *regs[RT2]=0; p->pop=0; 61926440Ssam } 62026440Ssam delnode(p->forw); 62129775Ssam if (tempreg(lastrand,r2)) 62229775Ssam uses[r2]=uses[r], uses[r]=0; 62326440Ssam redun3(p); 62426440Ssam newcode(p); redunm++; flow=r; 62529775Ssam } else if (p->op==MOV) { /* superfluous fetch */ 62626440Ssam int nmatch; 62726440Ssam char src[C2_ASIZE]; 62826440Ssam movit: 62929775Ssam for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) 63029775Ssam ; 63126440Ssam splitrand(p->forw); 63226440Ssam if (p->forw->op != INC && p->forw->op != DEC) 63326440Ssam lastrand=byondrd(p->forw); 63426440Ssam nmatch=0; 63526440Ssam for (preg=regs+RT1;*preg!=lastrand;preg++) 63626440Ssam if (r==isreg(*preg)) { 63729775Ssam cp2= *preg; cp1=src; 63829775Ssam while (*cp2++= *cp1++) 63929775Ssam ; 64029775Ssam ++nmatch; 64126440Ssam } 64226440Ssam if (nmatch==1) { 64329775Ssam if (has2ops(p->forw) && equstr(src,regs[RT2])) { 64426440Ssam p->forw->pop=0; 64529775Ssam p->forw->subop += (OP3-OP2)<<4; 64629775Ssam cp1=regs[RT3]; 64729775Ssam *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; 64826440Ssam } 64929775Ssam delnode(p); 65029775Ssam p=p->forw; 65129775Ssam if (tempreg(src,r2)) 65229775Ssam uses[r2]=uses[r], uses[r]=0; 65326440Ssam redun3(p); 65433359Sdonn newcode(p); redunm++; 65533359Sdonn return(p); /* avoid stale uses[] data */ 65629775Ssam } else 65729775Ssam splitrand(p); 65826440Ssam } 65929775Ssam } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && 66029775Ssam p->forw->subop&0xf && /* if base or index, then forget it */ 66129775Ssam compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) 66229775Ssam goto movit; 66326440Ssam } 66426440Ssam /* adjust 'lastrand' past any 'read' or 'modify' operands. */ 66526440Ssam lastrand=byondrd(p); 66626440Ssam /* a 'write' clobbers the register. */ 66729775Ssam if (tempreg(lastrand,r) || 66829775Ssam (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) { 66929775Ssam /* 67029775Ssam * Writing a dead register is useless, 67129775Ssam * but watch side effects 67229775Ssam */ 67326440Ssam switch (p->op) { 67426440Ssam #ifndef EMOD 67526440Ssam case EDIV: 67626440Ssam #endif EMOD 67729775Ssam case AOBLEQ: case AOBLSS: 67829775Ssam break; 67926440Ssam default: 68029775Ssam /* 68129775Ssam * If no direct uses, check for 68229775Ssam * use of condition codes 68329775Ssam */ 68426440Ssam if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { 68529775Ssam register struct node *q = p; 68629775Ssam 68729775Ssam while ((q = nonlab(q->forw))->op==JBR && 68829775Ssam q->subop==0) 68929775Ssam q=q->ref; /* cc unused, unchanged */ 69029775Ssam if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { 69129775Ssam /* ... and destroyed */ 69226440Ssam preg=regs+RT1; 69329775Ssam while (cp1 = *preg++) { 69429775Ssam if (cp1==lastrand && 69529775Ssam p->op != CLR && 69629775Ssam p->op != CVFL) { 69729775Ssam redunm++; 69829775Ssam delnode(p); 69929775Ssam return(p->forw); 70029775Ssam } 70129775Ssam if (equstr(cp1,lastrand)) 70229775Ssam break; 70326440Ssam } 70426440Ssam } 70526440Ssam } 70626440Ssam flow=r; 70726440Ssam } 70826440Ssam } 70929775Ssam if ((r=flow) >= 0) { 71029775Ssam olduse=uses[r], uses[r]=0; 71129775Ssam *(short *)(regs[r])=0; 71226440Ssam /* if r0 destroyed, dont keep r1 */ 71329775Ssam if (dblflg&1) { 71429775Ssam olduse1=uses[++r], uses[r]=0; 71529775Ssam *(short *)(regs[r])=0; 71626440Ssam } 71726440Ssam } 71826440Ssam /* now look for 'read' or 'modify' (read & write) uses */ 71926440Ssam preg=regs+RT1; 72026440Ssam while (*(cp1= *preg++)) { 72126440Ssam /* check for r */ 72233301Sdonn if (lastrand!=cp1 && tempreg(cp1,r)) { 72333301Sdonn int isunused; 72433301Sdonn if (isunused=(uses[r]==0)) { 72533301Sdonn uses[r]=p; 72633301Sdonn cp2=regs[r]; *cp2++=p->subop; 72733301Sdonn if ((p->op==SHAL || p->op==SHAR || 72833301Sdonn p->op==SHL || p->op==SHR) && 72933301Sdonn cp1==regs[RT1]) 73033301Sdonn cp2[-1] = BYTE; 73133301Sdonn if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) 73233301Sdonn cp2[-1] = LONG; 73333301Sdonn if (p->op==MOVA && cp1==regs[RT2]) 73433301Sdonn cp2[-1]=LONG; 73533301Sdonn } 73626440Ssam /* ediv/emod's 2nd operand is quad */ 73729775Ssam if (((p->op==EDIV 73826440Ssam #ifdef EMOD 73929775Ssam || p->op==EMOD 74026440Ssam #endif EMOD 74129775Ssam ) && cp1==regs[RT2] || (dblflg&2)) && 74229775Ssam ++r<NUSE && uses[r]==0) { 74333301Sdonn if (isunused) 74433301Sdonn *cp2=0; 74529775Ssam uses[r]=p; 74629775Ssam cp2=regs[r]; *cp2++=p->subop; 74733301Sdonn if (!isunused) 74833301Sdonn *cp2=0; 74926440Ssam } 75033301Sdonn if (!isunused) 75133301Sdonn continue; 75229775Ssam if (p->op==MOV || p->op==PUSH || p->op==CVT || 75329775Ssam p->op==MOVZ || p->op==COM || p->op==NEG || 75429775Ssam p->op==STF) { 75529775Ssam if (p->op!=PUSH) { 75626440Ssam cp1=regs[RT2]; 75729775Ssam if (tempreg(cp1,r)) { 75829775Ssam /* 75929775Ssam * reincarnation!! 76029775Ssam * (as in addl2 r0,r1; 76129775Ssam * movl r1,r0; ret) 76229775Ssam */ 76329775Ssam if (uses[r]==0) 76426440Ssam uses[r]=olduse; 76529775Ssam if ((dblflg&1) && uses[r+1]==0) 76626440Ssam uses[r+1]=olduse1; 76726440Ssam } 76829775Ssam if (p->op!=MOV) 76929775Ssam cp1=0; 77029775Ssam } else 77129775Ssam cp1="-(sp)"; 77229775Ssam if (cp1) 77329775Ssam while (*cp2++= *cp1++) 77429775Ssam ; 77529775Ssam else 77629775Ssam *cp2=0; 77729775Ssam } else 77829775Ssam *cp2=0; 77926440Ssam continue; 78026440Ssam } 78126440Ssam /* check for (r),[r] */ 78229775Ssam do { 78329775Ssam if (*cp1=='(' || *cp1=='[') { /* get register number */ 78429775Ssam char t; 78529775Ssam for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) 78629775Ssam ; 78729775Ssam t= *cp1; *cp1=0; 78829775Ssam if (tempreg(cp2,r) && 78929775Ssam (uses[r]==0 || uses[r]==p)) { 79029775Ssam uses[r]=p; 79129775Ssam regs[r][0] = 79229775Ssam (*--cp2=='[' ? OPX<<4 : OPB<<4); 79329775Ssam } 79429775Ssam *cp1=t; 79526440Ssam } 79626440Ssam } while (*++cp1); 79726440Ssam } 79826440Ssam #ifdef MOVAFASTER 79926440Ssam /* pushax or movax possibility? */ 80026440Ssam cp1=regs[RT1]; 80126440Ssam if (*cp1++=='$' && isstatic(cp1)) { 80226440Ssam if (p->op==MOV && p->subop==LONG) { 80326440Ssam if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { 80426440Ssam cp1=p->code; while (*cp1++!=','); p->code= --cp1; 80526440Ssam } 80626440Ssam p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; 80726440Ssam } else if (p->op==PUSH && p->subop==LONG) { 80826440Ssam p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; 80926440Ssam } else if (p->op==ADD && p->subop==U(LONG,OP3) 81026440Ssam && 0<=(r=isreg(regs[RT2]))) { 81126440Ssam cp1=cp2=p->code; ++cp1; 81226440Ssam do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; 81326440Ssam do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; 81426440Ssam if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} 81526440Ssam else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} 81626440Ssam if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} 81726440Ssam p->pop=0; 81826440Ssam } 81926440Ssam } 82026440Ssam #endif MOVAFASTER 82129775Ssam return (p); 82226440Ssam } 82326440Ssam 82426440Ssam /* try to eliminate STF's */ 82526440Ssam struct node * 82626440Ssam flops(q) 82726440Ssam register struct node *q; 82826440Ssam { 82926440Ssam register struct node *p; 83026440Ssam register int r; 83126440Ssam 83229775Ssam if(q->op!=STF || !tempreg(q->code,r)) 83326440Ssam return(q); 83426440Ssam if(uses[r]) { 83526440Ssam /* see if anyone destroys acc between us */ 83626440Ssam for(p=q->forw; p!=uses[r]; p=p->forw) 83726440Ssam switch(p->op) { 83826440Ssam case LABEL: 83926440Ssam case LDF: case LNF: case CVLF: case LDFD: 84026440Ssam case CVDF: case NEGF: case ADDF: case SUBF: 84126440Ssam case MULF: case DIVF: case SINF: case COSF: 84226440Ssam case ATANF: case LOGF: case SQRTF: case EXPF: 84326440Ssam return(q); 84426440Ssam } 84526440Ssam 84626440Ssam if(q->subop == p->subop) 84726440Ssam switch(p->op) { /* do it in the accumulator */ 84826440Ssam case LDF: /* redundant load */ 84926440Ssam delnode(p); nld++; 85026440Ssam p = p->forw; 85126440Ssam break; 85226440Ssam case LNF: /* stf r; lnf r ==> negf */ 85326440Ssam p->op = NEGF; 85426440Ssam p->pop = 0; 85526440Ssam p->code = 0; 85626440Ssam break; 85726440Ssam case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ 85826440Ssam { register char *s; 85926440Ssam register struct node *p1=p->forw; 86026440Ssam for(s=p->code; *s!=','; s++); 86126440Ssam *s = 0; 86226440Ssam if(isreg(p->code) == r) 86326440Ssam p->code = s+1; 86426440Ssam else { 86526440Ssam if(p1->op != CBR || isreg(s+1) != r) { 86626440Ssam *s = ','; 86726440Ssam return(q); 86826440Ssam } 86926440Ssam if(p1->subop > JNE) { 87026440Ssam p1->subop ^= 1; 87126440Ssam p1->pop = 0; 87226440Ssam nrevbr++; 87326440Ssam } 87426440Ssam } 87526440Ssam p->op = CMPF; 87626440Ssam p->pop = 0; 87726440Ssam } 87826440Ssam break; 87926440Ssam default: 88026440Ssam return(q); 88126440Ssam } 88226440Ssam else if(p->subop==LONG) { 88326440Ssam switch(p->op) { 88426440Ssam case TST: /* stf r; tstl r ==> tstf */ 88526440Ssam p->op = TSTF; 88626440Ssam p->code = 0; 88726440Ssam break; 88826440Ssam /* send directly to destination */ 88926440Ssam case MOV: /* stf r; movl r,x ==> stf x */ 89026440Ssam case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ 89126440Ssam if(q->subop == DOUBLE) { 89226440Ssam register struct node *b = p->back; 89326440Ssam /* assume b's 2nd arg is ok */ 89426440Ssam if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) 89526440Ssam return(q); 89626440Ssam delnode(b); redunm++; 89726440Ssam } 89826440Ssam if(p->op==PUSH) { 89926440Ssam if(q->subop == DOUBLE) { 90026440Ssam p->op = PUSHD; 90126440Ssam p->code = 0; 90226440Ssam } else { 90326440Ssam p->op = q->op; 90426440Ssam p->code = copy("-(sp)"); 90526440Ssam } 90626440Ssam } else { 90726440Ssam p->op = q->op; 90826440Ssam while(*p->code++ != ','); 90926440Ssam } 91026440Ssam break; 91126440Ssam default: 91226440Ssam return(q); 91326440Ssam } 91426440Ssam p->pop = 0; 91526440Ssam p->subop = q->subop; 91626440Ssam } else 91726440Ssam return(q); 91826440Ssam uses[r] = 0; 91926440Ssam if(q->subop == DOUBLE) 92026440Ssam uses[r+1] = 0; 92126440Ssam { /* undo any effect on uses in the area between p and q, 92226440Ssam * as we are going over it again */ 92326440Ssam register struct node *b; 92426440Ssam for(b=p; b!=q; b=b->back) { 92526440Ssam for(r=0; r<NUSE; r++) { 92626440Ssam if(uses[r] == b) 92726440Ssam uses[r] = 0; 92826440Ssam if(useacc == b) 92926440Ssam useacc = 0; 93026440Ssam } 93126440Ssam } 93226440Ssam } 93326440Ssam return(p->forw); /* make p the next for bflow */ 93426440Ssam } 93526440Ssam /* it's a store to reg which isnt used elsewhere */ 93626440Ssam if((p=q->forw)->op == CBR) { 93726440Ssam q->op = TSTF; 93826440Ssam q->pop = 0; 93926440Ssam q->code = 0; 94026440Ssam } else { 94126440Ssam delnode(q); nst++; 94226440Ssam if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { 94326440Ssam if(useacc == p) 94426440Ssam useacc = 0; 94526440Ssam return(p->forw); /* so ldmov can be used on p */ 94626440Ssam } 94726440Ssam } 94826440Ssam return(p); 94926440Ssam } 95026440Ssam 95126440Ssam /* try to change load/store sequences to movl */ 95226440Ssam ldmov(q) 95326440Ssam register struct node *q; 95426440Ssam { 95526440Ssam register struct node *p; 95626440Ssam register char *s, *pcod, *cp; 95726440Ssam char *dlsw(); 95826440Ssam 95926440Ssam p = q->back; 96026440Ssam if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) 96126440Ssam && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) 96226440Ssam return(0); 96326440Ssam pcod = p->code; 96426440Ssam cp = p->code; 96526440Ssam /* prepare args for movl/pushl */ 96626440Ssam if(q->op!=TSTF && q->subop==DOUBLE) { 96726440Ssam if(p->op == LDF) { 96826440Ssam if((s = dlsw(p->code)) == NULL) 96926440Ssam return(0); 97029670Ssam 97126440Ssam strcpy(line, s); 97226440Ssam if(q->op == STF) { 97326440Ssam strcat(line, ","); 97426440Ssam if((s = dlsw(q->code)) == NULL) 97526440Ssam return(0); 97626440Ssam strcat(line, s); 97726440Ssam p->op = MOV; 97826440Ssam } else 97926440Ssam p->op = PUSH; 98026440Ssam } else { /* LDFD */ 98126440Ssam if(q->op == STF) { 98226440Ssam if((s = dlsw(q->code)) == NULL) 98326440Ssam return(0); 98426440Ssam } else 98526440Ssam s = "-(sp)"; 98626440Ssam strcpy(line, s); 98726440Ssam p->op = CLR; 98826440Ssam } 98926440Ssam p->pop = 0; 99026440Ssam p->subop = LONG; 99126440Ssam p->code = copy(line); 99226440Ssam } else 99326440Ssam { 99426440Ssam if ((p->op == LDF) && (p->subop == DOUBLE) && 99526440Ssam (indexa(cp))) return(0); 99626440Ssam delnode(p); 99726440Ssam } 99826440Ssam strcpy(line, pcod); 99926440Ssam if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ 100026440Ssam strcat(line, ","); 100126440Ssam strcat(line, q->code); 100226440Ssam q->op = MOV; 100326440Ssam nst++; 100426440Ssam } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ 100526440Ssam q->op = TST; 100626440Ssam else /* ldd x; pushd ==> pushl x+4; pushl x */ 100726440Ssam q->op = PUSH; 100826440Ssam q->pop = 0; 100926440Ssam q->subop = LONG; 101026440Ssam q->code = copy(line); 101126440Ssam nld++; 101226440Ssam return(1); 101326440Ssam } 101426440Ssam 101526440Ssam /* reconstruct the address of l.s.w. of a double operand */ 101626440Ssam char * 101726440Ssam dlsw(d) 101826440Ssam register char *d; 101926440Ssam { 102029670Ssam register char *s, *t, *c; 102126440Ssam register int r; 102226440Ssam static char lsw[C2_ASIZE]; 102326440Ssam 102426440Ssam if(d[0] == '*' || d[0] == '$') 102526440Ssam return(NULL); 102629670Ssam if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) 102729670Ssam return(NULL); 102826440Ssam t = lsw; 102926440Ssam if((r=isreg(d)) >= 0) 103026440Ssam sprintf(t, "r%d", r+1); 103126440Ssam else { 103226440Ssam for(s=d; *s && *s!='('; *t++ = *s++) 103326440Ssam if(*s == '[') 103426440Ssam return(NULL); 103529670Ssam if(s!=d) 103629670Ssam *t++ = '+'; 103729670Ssam *t++ = '4'; 103826440Ssam while(*t++ = *s) 103929670Ssam if(*s++ == '[' ) 104029670Ssam { 104126440Ssam return(NULL); 104229670Ssam } 104326440Ssam } 104426440Ssam return(lsw); 104526440Ssam } 104629670Ssam checkexpr(p) 104729670Ssam register char *p; 104829670Ssam { 104929670Ssam 105029670Ssam while(*p && *p != ','){ 105129670Ssam if ((*p == '+' ) || (*p == '-')) 105229670Ssam return(1); 105329670Ssam *p++; 105429670Ssam } 105529670Ssam return(0); 105629670Ssam } 1057