void zzzcode(NODE * p, int c) { int sz; switch (c) { case 'C': /* remove arguments from stack after subroutine call */ sz = p->n_qual > 16 ? p->n_qual : 16; printf("\taddiu %s,%s,%d\n", rnames[SP], rnames[SP], sz); break; case 'D': /* long long comparison */ twollcomp(p); break; case 'E': /* emit emulated ops */ emulop(p); break; case 'F': /* emit emulate floating point ops */ fpemulop(p); break; case 'G': /* emit hardware floating-point compare op */ fpcmpops(p); break; case 'H': /* structure argument */ starg(p); break; case 'I': /* high part of init constant */ if (p->n_name[0] != '\0') comperr("named highword"); fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff); break; case 'O': /* 64-bit left and right shift operators */ shiftop(p); break; case 'Q': /* emit struct assign */ stasg(p); break; default: comperr("zzzcode %c", c); } }
void zzzcode(NODE *p, int c) { NODE *l; int pr, lr; char *ch; switch (c) { case 'A': /* swap st0 and st1 if right is evaluated second */ if ((p->n_su & DORIGHT) == 0) { if (logop(p->n_op)) printf(" fxch\n"); else printf("r"); } break; case 'C': /* remove from stack after subroutine call */ #ifdef notyet if (p->n_left->n_flags & FSTDCALL) break; #endif pr = p->n_qual; if (p->n_op == STCALL || p->n_op == USTCALL) pr += 4; if (p->n_flags & FFPPOP) printf(" fstp %%st(0)\n"); if (p->n_op == UCALL) return; /* XXX remove ZC from UCALL */ if (pr) printf(" addl $%d, %s\n", pr, rnames[ESP]); break; case 'D': /* Long long comparision */ twollcomp(p); break; case 'F': /* Structure argument */ if (p->n_stalign != 0) /* already on stack */ starg(p); break; case 'G': /* Floating point compare */ fcomp(p); break; case 'H': /* assign of longlong between regs */ rmove(DECRA(p->n_right->n_reg, 0), DECRA(p->n_left->n_reg, 0), LONGLONG); break; case 'I': /* float casts */ fcast(p); break; case 'J': /* convert unsigned long long to floating point */ ulltofp(p); break; case 'K': /* Load longlong reg into another reg */ rmove(regno(p), DECRA(p->n_reg, 0), LONGLONG); break; case 'M': /* Output sconv move, if needed */ l = getlr(p, 'L'); /* XXX fixneed: regnum */ pr = DECRA(p->n_reg, 0); lr = DECRA(l->n_reg, 0); if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) || (pr == CL && lr == ECX) || (pr == DL && lr == EDX)) ; else printf(" movb %%%cl,%s\n", rnames[lr][2], rnames[pr]); l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ break; case 'N': /* output extended reg name */ printf("%s", rnames[getlr(p, '1')->n_rval]); break; case 'O': /* print out emulated ops */ pr = 16; if (p->n_op == RS || p->n_op == LS) { llshft(p); break; } else if (p->n_op == MUL) { printf("\timull %%ecx, %%edx\n"); printf("\timull %%eax, %%esi\n"); printf("\taddl %%edx, %%esi\n"); printf("\tmull %%ecx\n"); printf("\taddl %%esi, %%edx\n"); break; } expand(p, INCREG, "\tpushl UR\n\tpushl AR\n"); expand(p, INCREG, "\tpushl UL\n\tpushl AL\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 ch = 0, comperr("ZO"); #ifdef ELFABI printf("\tcall " EXPREFIX "__%sdi3%s\n\taddl $%d,%s\n", ch, (kflag ? "@PLT" : ""), pr, rnames[ESP]); #else printf("\tcall " EXPREFIX "__%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]); #endif break; case 'P': /* push hidden argument on stack */ printf("\tleal -%d(%%ebp),", stkpos); adrput(stdout, getlr(p, '1')); printf("\n\tpushl "); adrput(stdout, getlr(p, '1')); putchar('\n'); break; case 'Q': /* emit struct assign */ /* * With <= 16 bytes, put out mov's, otherwise use movsb/w/l. * esi/edi/ecx are available. * XXX should not need esi/edi if not rep movsX. * XXX can save one insn if src ptr in reg. */ switch (p->n_stsize) { case 1: expand(p, INAREG, " movb (%esi),%cl\n"); expand(p, INAREG, " movb %cl,AL\n"); break; case 2: expand(p, INAREG, " movw (%esi),%cx\n"); expand(p, INAREG, " movw %cx,AL\n"); break; case 4: expand(p, INAREG, " movl (%esi),%ecx\n"); expand(p, INAREG, " movl %ecx,AL\n"); break; default: expand(p, INAREG, " leal AL,%edi\n"); if (p->n_stsize <= 16 && (p->n_stsize & 3) == 0) { printf(" movl (%%esi),%%ecx\n"); printf(" movl %%ecx,(%%edi)\n"); printf(" movl 4(%%esi),%%ecx\n"); printf(" movl %%ecx,4(%%edi)\n"); if (p->n_stsize > 8) { printf(" movl 8(%%esi),%%ecx\n"); printf(" movl %%ecx,8(%%edi)\n"); } if (p->n_stsize == 16) { printf("\tmovl 12(%%esi),%%ecx\n"); printf("\tmovl %%ecx,12(%%edi)\n"); } } else { if (p->n_stsize > 4) { printf("\tmovl $%d,%%ecx\n", p->n_stsize >> 2); printf(" rep movsl\n"); } if (p->n_stsize & 2) printf(" movsw\n"); if (p->n_stsize & 1) printf(" movsb\n"); } break; } break; case 'S': /* emit eventual move after cast from longlong */ pr = DECRA(p->n_reg, 0); lr = p->n_left->n_rval; switch (p->n_type) { case CHAR: case UCHAR: if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' && rnames[pr][1] == rnames[lr][1]) break; if (rnames[lr][2] == 'x') { printf("\tmovb %%%cl,%s\n", rnames[lr][1], rnames[pr]); break; } /* Must go via stack */ expand(p, INAREG, "\tmovl AL,A2\n"); expand(p, INBREG, "\tmovb A2,A1\n"); #ifdef notdef /* cannot use freetemp() in instruction emission */ s = BITOOR(freetemp(1)); printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s); printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]); #endif break; case SHORT: case USHORT: if (rnames[lr][1] == rnames[pr][2] && rnames[lr][2] == rnames[pr][3]) break; printf("\tmovw %%%c%c,%%%s\n", rnames[lr][1], rnames[lr][2], rnames[pr]+2); break; case INT: case UNSIGNED: if (rnames[lr][1] == rnames[pr][2] && rnames[lr][2] == rnames[pr][3]) break; printf("\tmovl %%e%c%c,%s\n", rnames[lr][1], rnames[lr][2], rnames[pr]); break; default: if (rnames[lr][1] == rnames[pr][2] && rnames[lr][2] == rnames[pr][3]) break; comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]); break; } break; default: comperr("zzzcode %c", c); }
void zzzcode(NODE *p, int c) { struct attr *ap; NODE *l; int pr, lr; char *ch; switch (c) { case 'A': /* swap st0 and st1 if right is evaluated second */ if ((p->n_su & DORIGHT) == 0) { if (logop(p->n_op)) printf(" fxch\n"); else printf("r"); } break; case 'C': /* remove from stack after subroutine call */ #ifdef GCC_COMPAT if (attr_find(p->n_left->n_ap, GCC_ATYP_STDCALL)) break; #endif pr = p->n_qual; if (attr_find(p->n_ap, ATTR_I386_FPPOP)) printf(" fstp %%st(0)\n"); if (p->n_op == UCALL) return; /* XXX remove ZC from UCALL */ if (pr) printf(" addl $%d, %s\n", pr, rnames[ESP]); #if defined(os_openbsd) ap = attr_find(p->n_ap, ATTR_P2STRUCT); if (p->n_op == STCALL && (ap->iarg(0) == 1 || ap->iarg(0) == 2 || ap->iarg(0) == 4 || ap->iarg(0) == 8)) { /* save on stack */ printf("\tmovl %%eax,-%d(%%ebp)\n", stkpos); printf("\tmovl %%edx,-%d(%%ebp)\n", stkpos+4); printf("\tleal -%d(%%ebp),%%eax\n", stkpos); } #endif break; case 'D': /* Long long comparision */ twollcomp(p); break; case 'F': /* Structure argument */ starg(p); break; case 'G': /* Floating point compare */ fcomp(p); break; case 'H': /* assign of longlong between regs */ rmove(DECRA(p->n_right->n_reg, 0), DECRA(p->n_left->n_reg, 0), LONGLONG); break; case 'I': /* float casts */ fcast(p); break; case 'J': /* convert unsigned long long to floating point */ ulltofp(p); break; case 'K': /* Load longlong reg into another reg */ rmove(regno(p), DECRA(p->n_reg, 0), LONGLONG); break; case 'M': /* Output sconv move, if needed */ l = getlr(p, 'L'); /* XXX fixneed: regnum */ pr = DECRA(p->n_reg, 0); lr = DECRA(l->n_reg, 0); if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) || (pr == CL && lr == ECX) || (pr == DL && lr == EDX)) ; else printf(" movb %%%cl,%s\n", rnames[lr][2], rnames[pr]); l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ break; case 'N': /* output extended reg name */ printf("%s", rnames[getlr(p, '1')->n_rval]); break; case 'O': /* print out emulated ops */ pr = 16; if (p->n_op == RS || p->n_op == LS) { llshft(p); break; } else if (p->n_op == MUL) { printf("\timull %%ecx, %%edx\n"); printf("\timull %%eax, %%esi\n"); printf("\taddl %%edx, %%esi\n"); printf("\tmull %%ecx\n"); printf("\taddl %%esi, %%edx\n"); break; } expand(p, INCREG, "\tpushl UR\n\tpushl AR\n"); expand(p, INCREG, "\tpushl UL\n\tpushl AL\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 ch = 0, comperr("ZO"); #ifdef ELFABI printf("\tcall " EXPREFIX "__%sdi3%s\n\taddl $%d,%s\n", ch, (kflag ? "@PLT" : ""), pr, rnames[ESP]); #else printf("\tcall " EXPREFIX "__%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]); #endif break; case 'Q': /* emit struct assign */ /* * Put out some combination of movs{b,w,l} * esi/edi/ecx are available. */ expand(p, INAREG, " leal AL,%edi\n"); ap = attr_find(p->n_ap, ATTR_P2STRUCT); if (ap->iarg(0) < 32) { int i = ap->iarg(0) >> 2; while (i) { expand(p, INAREG, " movsl\n"); i--; } } else {
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 zzzcode(NODE *p, int c) { struct attr *ap; NODE *l; int pr, lr; char *ch; char sv; switch (c) { case 'A': /* swap st0 and st1 if right is evaluated second */ if ((p->n_su & DORIGHT) == 0) { if (logop(p->n_op)) printf(" fxch\n"); else printf("r"); } break; case 'C': /* remove from stack after subroutine call */ #ifdef notdef if (p->n_left->n_flags & FSTDCALL) break; #endif pr = p->n_qual; if (attr_find(p->n_ap, ATTR_I86_FPPOP)) printf(" fstp st(0)\n"); if (p->n_op == UCALL) return; /* XXX remove ZC from UCALL */ if (pr) { if (pr == 2) printf(" inc sp\n inc sp\n"); else printf(" add sp,#%d\n", pr); } break; case 'D': /* Long comparision */ twollcomp(p); break; case 'F': /* Structure argument */ starg(p); break; case 'G': /* Floating point compare */ fcomp(p); break; case 'H': /* assign of long between regs */ rmove(DECRA(p->n_right->n_reg, 0), DECRA(p->n_left->n_reg, 0), LONGLONG); break; case 'I': /* float casts */ fcast(p); break; case 'J': /* convert unsigned long long to floating point */ ulltofp(p); break; case 'K': /* Load long reg into another reg */ rmove(regno(p), DECRA(p->n_reg, 0), LONGLONG); break; case 'M': /* Output sconv move, if needed */ l = getlr(p, 'L'); /* XXX fixneed: regnum */ pr = DECRA(p->n_reg, 0); lr = DECRA(l->n_reg, 0); if ((pr == AL && lr == AX) || (pr == BL && lr == BX) || (pr == CL && lr == CX) || (pr == DL && lr == DX)) ; else printf(" mov %s, %cL\n", rnames[pr], rnames[lr][1]); l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ break; case 'N': /* output extended reg name */ printf("%s", rnames[getlr(p, '1')->n_rval]); break; case 'O': /* print out emulated ops */ pr = 8; sv = 'l'; #if 0 if (p->n_op == RS || p->n_op == LS) { llshft(p); break; } #endif if (p->n_op != RS && p->n_op != LS) { /* For 64bit we will need to push pointers not u64 */ expand(p, INCREG, "\tpush UR\n\tpush AR\n"); expand(p, INCREG, "\tpush UL\n\tpush AL\n"); } else { /* AR is a BREG so this goes wrong.. need an AREG but putting an AREG in the table rule makes the compiler shit itself - FIXME */ expand(p, INAREG, "\tpush AR\n"); expand(p, INCREG, "\tpush UL\n\tpush AL\n"); pr = 6; } if (p->n_type == LONGLONG || p->n_type == ULONGLONG) sv = 'L'; if (p->n_op == DIV && (p->n_type == ULONG || p->n_type == ULONGLONG)) ch = "udiv"; else if (p->n_op == MUL && (p->n_type == ULONG || p->n_type == ULONGLONG)) ch = "umul"; else if (p->n_op == DIV) ch = "div"; else if (p->n_op == MUL) ch = "mul"; else if (p->n_op == MOD && (p->n_type == ULONG || p->n_type == ULONGLONG)) ch = "umod"; else if (p->n_op == MOD) ch = "mod"; else if (p->n_op == LS) ch = "ls"; else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == ULONGLONG)) ch = "rs"; else if (p->n_op == RS) ch = "urs"; else ch = 0, comperr("ZO"); printf("\tcall " EXPREFIX "__%c%sdi3\n\tadd %s,#%d\n", sv, ch, rnames[SP], pr); break; case 'P': /* typeless right hand */ suppress_type = 1; break; case 'Q': /* emit struct assign */ /* * Put out some combination of movs{b,w} * si/di/cx are available. * FIXME: review es: and direction flag implications */ expand(p, INAREG, " lea al,di\n"); ap = attr_find(p->n_ap, ATTR_P2STRUCT); if (ap->iarg(0) < 32) { int i = ap->iarg(0) >> 1; while (i) { expand(p, INAREG, " movsw\n"); i--; } } else {