/* * Convert an unsigned long long to floating point number. */ static void ulltofp(NODE *p) { #if defined(ELFABI) || defined(PECOFFABI) static int loadlab; int jmplab; if (loadlab == 0) { loadlab = getlab2(); expand(p, 0, " .data\n"); printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab); expand(p, 0, " .text\n"); } jmplab = getlab2(); expand(p, 0, " pushl UL\n pushl AL\n"); expand(p, 0, " fildq (%esp)\n"); expand(p, 0, " addl $8,%esp\n"); expand(p, 0, " cmpl $0,UL\n"); printf(" jge " LABFMT "\n", jmplab); printf(" fldt " LABFMT "%s\n", loadlab, kflag ? "@GOTOFF" : ""); printf(" faddp %%st,%%st(1)\n"); printf(LABFMT ":\n", jmplab); #else #error incomplete implementation #endif }
/* * Convert an unsigned long long to floating point number. */ static void ulltofp(NODE *p) { int jmplab = getlab2(); if (loadlab == 0) loadlab = getlab2(); expand(p, 0, " movl UL,4+A2\n movl AL,A2\n"); expand(p, 0, " fildq A2\n"); expand(p, 0, " test UL,UL\n"); printf(" jge " LABFMT "\n", jmplab); printf(" fadds " LABFMT "%s\n", loadlab, kflag ? "@GOTOFF" : ""); printf(LABFMT ":\n", jmplab); }
/* * 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); }
void prologue(int regs, int autos) { int i, addto; offlab = getlab2(); if (regs < 0 || autos < 0) { /* * non-optimized code, jump to epilogue for code generation. */ ftlab1 = getlab2(); ftlab2 = getlab2(); printf(" jrst L%d\n", ftlab1); printf("L%d:\n", ftlab2); } else { /* * We here know what register to save and how much to * add to the stack. */ autos = autos + (SZINT-1); addto = (autos - AUTOINIT)/SZINT + (MAXRVAR-regs); if (addto || gflag) { printf(" push %s,%s\n",rnames[017], rnames[016]); printf(" move %s,%s\n", rnames[016],rnames[017]); for (i = regs; i < MAXRVAR; i++) { int db = ((i+1) < MAXRVAR); printf(" %smovem %s,0%o(%s)\n", db ? "d" : "", rnames[i+1], i+1-regs, rnames[016]); if (db) i++; } if (addto) printf(" addi %s,0%o\n", rnames[017], addto); } else offarg = 1; } }
/* * 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); }
/* * Convert an unsigned long long to floating point number. */ static void ulltofp(NODE *p) { int jmplab; jmplab = getlab2(); expand(p, 0, " push UL\n push AL\n"); expand(p, 0, " fildq [sp]\n"); expand(p, 0, " add sp, #8\n"); expand(p, 0, " cmp UL, #0\n"); printf(" jge " LABFMT "\n", jmplab); printf(" faddp %%st,%%st(1)\n"); printf(LABFMT ":\n", jmplab); }
/* * Print out the prolog assembler. * addto and regoff are already calculated. */ void prologue(struct interpass_prolog *ipp) { printf(" .word 0x%llx\n", (unsigned long long)ipp->ipp_regs[0]); if (p2maxautooff) printf(" subl2 $%d,%%sp\n", p2maxautooff); if (pflag) { int i = getlab2(); printf("\tmovab\t" LABFMT ",%%r0\n", i); printf("\tjsb\t__mcount\n"); printf("\t.data\n"); printf("\t.align 2\n"); printf(LABFMT ":\t.long\t0\n", i); printf("\t.text\n"); } }
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); }