efcode(){ /* code for the end of a function */ if( strftn ){ /* copy output (in r0) to caller */ register struct symtab *p; register int stlab; register int count; int size; p = &stab[curftn]; deflab( retlab ); stlab = getlab(); printf( " mov $L%d,r1\n", stlab ); size = tsize( DECREF(p->stype), p->dimoff, p->sizoff ) / SZCHAR; count = size/2; while( count-- ) { printf( " mov (r0)+,(r1)+\n" ); } printf( " mov $L%d,r0\n", stlab ); printf( " .bss\nL%d: .=.+%d.\n .text\n", stlab, size ); /* turn off strftn flag, so return sequence will be generated */ strftn = 0; } branch( retlab ); p2bend(); }
/* * Emit code to compare two longlong numbers. */ static void twollcomp(NODE *p) { int o = p->n_op; int s = getlab2(); int e = p->n_label; int cb1, cb2; if (o >= ULE) o -= (ULE-LE); switch (o) { case NE: cb1 = 0; cb2 = NE; break; case EQ: cb1 = NE; cb2 = 0; break; case LE: case LT: cb1 = GT; cb2 = LT; break; case GE: case GT: cb1 = LT; cb2 = GT; break; default: cb1 = cb2 = 0; /* XXX gcc */ } if (p->n_op >= ULE) cb1 += 4, cb2 += 4; expand(p, 0, "\tsub A1,UL,UR\t# compare 64-bit values (upper)\n"); if (cb1) { printf("\t"); hopcode(' ', cb1); expand(p, 0, "A1"); printf("," LABFMT "\n", s); printf("\tnop\n"); } if (cb2) { printf("\t"); hopcode(' ', cb2); expand(p, 0, "A1"); printf("," LABFMT "\n", e); printf("\tnop\n"); } expand(p, 0, "\tsub A1,AL,AR\t# (and lower)\n"); printf("\t"); hopcode(' ', o); expand(p, 0, "A1"); printf("," LABFMT "\n", e); printf("\tnop\n"); deflab(s); }
/* * Emit code to compare two longlong numbers. */ static void twollcomp(NODE *p) { int u; int s = getlab2(); int e = p->n_label; int cb1, cb2; u = p->n_op; switch (p->n_op) { case NE: cb1 = 0; cb2 = NE; break; case EQ: cb1 = NE; cb2 = 0; break; case LE: case LT: u += (ULE-LE); /* FALLTHROUGH */ case ULE: case ULT: cb1 = GT; cb2 = LT; break; case GE: case GT: u += (ULE-LE); /* FALLTHROUGH */ case UGE: case UGT: cb1 = LT; cb2 = GT; break; default: cb1 = cb2 = 0; /* XXX gcc */ } if (p->n_op >= ULE) cb1 += 4, cb2 += 4; expand(p, 0, " cmpl UR,UL\n"); if (cb1) cbgen(cb1, s); if (cb2) cbgen(cb2, e); expand(p, 0, " cmpl AR,AL\n"); cbgen(u, e); deflab(s); }
void zzzcode(NODE *p, int c) { NODE *l, *r; TWORD t; int m; char *ch; switch (c) { case 'N': /* logical ops, turned into 0-1 */ /* use register given by register 1 */ cbgen( 0, m=getlab2()); deflab( p->n_label ); printf( " clrl %s\n", rnames[getlr( p, '1' )->n_rval] ); deflab( m ); return; case 'A': /* Assign a constant directly to a memory position */ printf("\t"); if (p->n_type < LONG || ISPTR(p->n_type)) casg(p); else casg64(p); printf("\n"); break; case 'B': /* long long compare */ twollcomp(p); break; case 'C': /* num words pushed on arg stack */ printf("$%d", p->n_qual); break; case 'D': /* INCR and DECR */ zzzcode(p->n_left, 'A'); printf("\n "); #if 0 case 'E': /* INCR and DECR, FOREFF */ if (p->n_right->n_lval == 1) { printf("%s", (p->n_op == INCR ? "inc" : "dec") ); prtype(p->n_left); printf(" "); adrput(stdout, p->n_left); return; } printf("%s", (p->n_op == INCR ? "add" : "sub") ); prtype(p->n_left); printf("2 "); adrput(stdout, p->n_right); printf(","); adrput(p->n_left); return; #endif case 'F': /* register type of right operand */ { register NODE *n; register int ty; n = getlr( p, 'R' ); ty = n->n_type; if (x2debug) printf("->%d<-", ty); if ( ty==DOUBLE) printf("d"); else if ( ty==FLOAT ) printf("f"); else printf("l"); return; } case 'G': /* emit conversion instructions */ sconv(p); break; case 'J': /* jump or ret? */ { struct interpass *ip = DLIST_PREV((struct interpass *)p2env.epp, qelem); if (ip->type != IP_DEFLAB || ip->ip_lbl != getlr(p, 'L')->n_lval) expand(p, FOREFF, "jbr LL"); else printf("ret"); } break; case 'L': /* type of left operand */ case 'R': /* type of right operand */ { register NODE *n; n = getlr ( p, c); if (x2debug) printf("->%d<-", n->n_type); prtype(n); return; } case 'O': /* print out emulated ops */ expand(p, FOREFF, "\tmovq AR,-(%sp)\n"); expand(p, FOREFF, "\tmovq AL,-(%sp)\n"); if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv"; else if (p->n_op == DIV) ch = "div"; else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod"; else if (p->n_op == MOD) ch = "mod"; else if (p->n_op == MUL) ch = "mul"; else ch = 0, comperr("ZO %d", p->n_op); printf("\tcalls $4,__%sdi3\n", ch); break; case 'Z': /* complement mask for bit instr */ printf("$%Ld", ~p->n_right->n_lval); return; case 'U': /* 32 - n, for unsigned right shifts */ t = DEUNSIGN(p->n_left->n_type); m = t == CHAR ? 8 : t == SHORT ? 16 : 32; printf("$" CONFMT, m - p->n_right->n_lval); return; case 'T': /* rounded structure length for arguments */ { int size; size = p->n_stsize; SETOFF( size, 4); printf("$%d", size); return; } case 'S': /* structure assignment */ { register int size; size = p->n_stsize; l = r = NULL; /* XXX gcc */ if( p->n_op == STASG ){ l = p->n_left; r = p->n_right; } else if( p->n_op == STARG ){ /* store an arg into a temporary */ printf("\tsubl2 $%d,%%sp\n", size < 4 ? 4 : size); l = mklnode(OREG, 0, SP, INT); r = p->n_left; } else cerror( "STASG bad" ); if( r->n_op == ICON ) r->n_op = NAME; else if( r->n_op == REG ) r->n_op = OREG; else if( r->n_op != OREG ) cerror( "STASG-r" ); if (size != 0) { if( size <= 0 || size > 65535 ) cerror("structure size <0=0 or >65535"); switch(size) { case 1: printf(" movb "); break; case 2: printf(" movw "); break; case 4: printf(" movl "); break; case 8: printf(" movq "); break; default: printf(" movc3 $%d,", size); break; } adrput(stdout, r); printf(","); adrput(stdout, l); printf("\n"); } if( r->n_op == NAME ) r->n_op = ICON; else if( r->n_op == OREG ) r->n_op = REG; if (p->n_op == STARG) tfree(l); } break; default: comperr("illegal zzzcode '%c'", c); } }
void prologue(struct interpass_prolog *ipp) { ftype = ipp->ipp_type; #if 0 if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR) comperr("fix prologue register savings", ipp->ipp_regs); #endif printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n"); if (ipp->ipp_vis) printf(" PUBLIC %s\n", ipp->ipp_name); printf("%s:\n", ipp->ipp_name); #if 0 if (xsaveip) { /* Optimizer running, save space on stack */ addto = (p2maxautooff - AUTOINIT)/SZCHAR; printf(" enter #%d\n", addto); } else { #endif /* non-optimized code, jump to epilogue for code generation */ ftlab1 = getlab2(); ftlab2 = getlab2(); printf(" jmp.w " LABFMT "\n", ftlab1); deflab(ftlab2); } /* * End of block. */ void eoftn(struct interpass_prolog *ipp) { #if 0 if (ipp->ipp_regs != MINRVAR) comperr("fix eoftn register savings %x", ipp->ipp_regs); #endif // if (xsaveip == 0) addto = (p2maxautooff - AUTOINIT)/SZCHAR; /* return from function code */ //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary? /* If retval is a pointer and not a function pointer, put in A0 */ if (ISPTR(DECREF(ipp->ipp_type)) && !ISFTN(DECREF(DECREF(ipp->ipp_type)))) printf(" mov.w r0,a0\n"); /* struct return needs special treatment */ if (ftype == STRTY || ftype == UNIONTY) { comperr("fix struct return in eoftn"); } else printf(" exitd\n"); /* Prolog code */ // if (xsaveip == 0) { deflab(ftlab1); printf(" enter #%d\n", addto); printf(" jmp.w " LABFMT "\n", ftlab2); //} } /* * add/sub/... * * Param given: */ void hopcode(int f, int o) { char *str; switch (o) { case PLUS: str = "add"; break; case MINUS: str = "sub"; break; case AND: str = "and"; break; case OR: str = "or"; break; case ER: str = "xor"; break; default: comperr("hopcode2: %d", o); str = 0; /* XXX gcc */ } printf("%s.%c", str, f); }