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; 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; 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 {