static NODE * moveargs(NODE *p, int *regp) { NODE *r, **rp; int lastreg; int reg; if (p->n_op == CM) { p->n_left = moveargs(p->n_left, regp); r = p->n_right; rp = &p->n_right; } else { r = p; rp = &p; } lastreg = A0 + nargregs - 1; reg = *regp; if (reg > lastreg && r->n_op != STARG) *rp = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap); else if (r->n_op == STARG) { *rp = movearg_struct(r, p, regp); } else if (DEUNSIGN(r->n_type) == LONGLONG) { *rp = movearg_64bit(r, regp); } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { /* XXX bounce in and out of temporary to change to longlong */ NODE *t1 = tempnode(0, LONGLONG, 0, 0); int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); t1 = movearg_64bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); if (p->n_op == CM) { p->n_left = buildtree(CM, p->n_left, t1); p->n_right = r; } else { p = buildtree(CM, t1, r); } } else if (r->n_type == FLOAT) { /* XXX bounce in and out of temporary to change to int */ NODE *t1 = tempnode(0, INT, 0, 0); int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); t1 = movearg_32bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); if (p->n_op == CM) { p->n_left = buildtree(CM, p->n_left, t1); p->n_right = r; } else { p = buildtree(CM, t1, r); } } else { *rp = movearg_32bit(r, regp); } return p; }
/* * Do the actual conversion of offstar-found OREGs into real OREGs. * For simple OREGs conversion should already be done. */ void myormake(NODE *q) { static int shtbl[] = { 1,2,4,8 }; NODE *p, *r; CONSZ c = 0; int r1, r2, sh; int mkconv = 0; char *n = ""; #define risreg(p) (p->n_op == REG) if (x2debug) { printf("myormake(%p)\n", q); fwalk(q, e2print, 0); } r1 = r2 = MAXREGS; sh = 1; r = p = q->n_left; if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { c = p->n_left->n_lval; n = p->n_left->n_name; p = p->n_right; } if (p->n_op == PLUS && risreg(p->n_left)) { r1 = regno(p->n_left); p = p->n_right; } if (findls(p, 1)) { if (p->n_op == SCONV) p = p->n_left; sh = shtbl[(int)p->n_right->n_lval]; r2 = regno(p->n_left); mkconv = 1; } else if (risreg(p)) { r2 = regno(p); mkconv = 1; } //else // comperr("bad myormake tree"); if (mkconv == 0) return; q->n_op = OREG; q->n_lval = c; q->n_rval = R2PACK(r1, r2, sh); q->n_name = n; tfree(r); if (x2debug) { printf("myormake converted %p\n", q); fwalk(q, e2print, 0); } }
/* * code for the end of a function * deals with struct return here * The return value is in (or pointed to by) RETREG. */ void efcode(void) { struct symtab *sp; extern int gotnr; TWORD t; NODE *p, *r, *l; int typ, ssz, rno; gotnr = 0; /* new number for next fun */ sp = cftnsp; t = DECREF(sp->stype); if (t != STRTY && t != UNIONTY) return; /* XXX should have one routine for this */ ngpr = nsse = 0; if ((typ = argtyp(t, sp->sdf, sp->sap)) == STRREG || typ == STRCPX) { /* Cast to long pointer and move to the registers */ /* XXX can overrun struct size */ /* XXX check carefully for SSE members */ if ((ssz = tsize(t, sp->sdf, sp->sap)) > SZLONG*2) cerror("efcode1"); if (typ == STRCPX) { t = DOUBLE; rno = XMM0; } else { t = LONG; rno = RAX; } if (ssz > SZLONG) { p = block(REG, NIL, NIL, INCREF(t), 0, 0); regno(p) = RAX; p = buildtree(UMUL, buildtree(PLUS, p, bcon(1)), NIL); ecomp(movtoreg(p, rno+1)); } p = block(REG, NIL, NIL, INCREF(t), 0, 0); regno(p) = RAX; p = buildtree(UMUL, p, NIL); ecomp(movtoreg(p, rno)); } else if (typ == STRMEM) { r = block(REG, NIL, NIL, INCREF(t), sp->sdf, sp->sap); regno(r) = RAX; r = buildtree(UMUL, r, NIL); l = tempnode(stroffset, INCREF(t), sp->sdf, sp->sap); l = buildtree(UMUL, l, NIL); ecomp(buildtree(ASSIGN, l, r)); l = block(REG, NIL, NIL, LONG, 0, 0); regno(l) = RAX; r = tempnode(stroffset, LONG, 0, 0); ecomp(buildtree(ASSIGN, l, r)); } else cerror("efcode"); }
/* setup the hidden pointer to struct return parameter * used by bfcode() */ static void param_retstruct(void) { NODE *p, *q; p = tempnode(0, PTR-FTN+cftnsp->stype, 0, cftnsp->sap); rvnr = regno(p); q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap); regno(q) = R0; p = buildtree(ASSIGN, p, q); ecomp(p); }
/* setup a float param on the stack * used by bfcode() */ static void param_float(struct symtab *sym, int *argofsp, int dotemps) { NODE *p, *q, *t; int tmpnr; /* * we have to dump the float from the general register * into a temp, since the register allocator doesn't like * floats to be in CLASSA. This may not work for -xtemps. */ t = tempnode(0, INT, 0, 0); tmpnr = regno(t); q = block(REG, NIL, NIL, INT, 0, 0); q->n_rval = R0 + (*argofsp)++; p = buildtree(ASSIGN, t, q); ecomp(p); if (dotemps) { sym->soffset = tmpnr; sym->sflags |= STNODE; } else { q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap); p = nametree(sym); p = buildtree(ASSIGN, p, q); ecomp(p); } }
NODE * builtin_return_address(const struct bitable *bt, NODE *a) { NODE *f; if (a->n_op != ICON) goto bad; if (a->n_lval != 0) werror("unsupported argument"); tfree(a); f = block(REG, NIL, NIL, INCREF(PTR+CHAR), 0, 0); regno(f) = FPREG; f = block(UMUL, block(PLUS, f, bcon(16), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0); f = makety(f, PTR+VOID, 0, 0, 0); return f; bad: uerror("bad argument to __builtin_return_address"); return bcon(0); }
/* * code for the end of a function * deals with struct return here */ void efcode(void) { NODE *p, *q; // int sz; #if 0 /* restore ac3 */ p = block(REG, 0, 0, INT, 0, 0); regno(p) = 3; q = tempnode(ac3temp, INT, 0, 0); ecomp(buildtree(ASSIGN, p, q)); #endif if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; cerror("efcode"); /* address of return struct is in eax */ /* create a call to memcpy() */ /* will get the result in eax */ p = block(REG, NIL, NIL, CHAR+PTR, 0, 0); // p->n_rval = EAX; q = block(OREG, NIL, NIL, CHAR+PTR, 0, 0); // q->n_rval = EBP; q->n_lval = 8; /* return buffer offset */ p = block(CM, q, p, INT, 0, 0); // sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; // p = block(CM, p, bcon(sz), INT, 0, 0); p->n_right->n_name = ""; p = block(CALL, bcon(0), p, CHAR+PTR, 0, 0); p->n_left->n_name = "memcpy"; p = clocal(p); send_passt(IP_NODE, p); }
NODE * builtin_frame_address(const struct bitable *bt, NODE *a) { int nframes; NODE *f; if (a->n_op != ICON) goto bad; nframes = a->n_lval; tfree(a); f = block(REG, NIL, NIL, PTR+CHAR, 0, 0); regno(f) = FPREG; while (nframes--) { f = block(UMUL, block(PLUS, f, bcon(12), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0); f = makety(f, PTR+CHAR, 0, 0, 0); } return f; bad: uerror("bad argument to __builtin_frame_address"); return bcon(0); }
NODE * builtin_return_address(const struct bitable *bt, NODE *a) { int nframes; NODE *f; if (a->n_op != ICON) goto bad; nframes = (int)a->n_lval; tfree(a); f = block(REG, NIL, NIL, PTR+VOID, 0, 0); regno(f) = FPREG; while (nframes--) f = block(UMUL, f, NIL, PTR+VOID, 0, 0); f = block(PLUS, f, bcon(2), INCREF(PTR+VOID), 0, 0); f = buildtree(UMUL, f, NIL); return f; bad: uerror("bad argument to __builtin_return_address"); return bcon(0); }
/* * Do the actual conversion of offstar-found OREGs into real OREGs. */ void myormake(NODE *p) { NODE *q = p->n_left; if (x2debug) { printf("myormake(%p)\n", p); fwalk(p, e2print, 0); } if (inctree(q)) { if (q->n_left->n_left->n_op == TEMP) return; p->n_op = OREG; p->n_lval = 0; /* Add support for index offset */ p->n_rval = R2PACK(regno(q->n_left->n_left), 0, 1); tfree(q); return; } if (q->n_op != OREG) return; p->n_op = OREG; p->n_lval = q->n_lval; p->n_rval = R2PACK(q->n_rval, 0, 0); nfree(q); }
/* * code for the beginning of a function; a is an array of * indices in symtab for the arguments; n is the number */ void bfcode(struct symtab **sp, int cnt) { struct symtab *sp2; NODE *n; int i; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Function returns struct, adjust arg offset */ for (i = 0; i < cnt; i++) sp[i]->soffset += SZPOINT(INT); } if (xtemps == 0) return; /* put arguments in temporaries */ for (i = 0; i < cnt; i++) { if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; sp2 = sp[i]; n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); n = buildtree(ASSIGN, n, nametree(sp2)); sp[i]->soffset = regno(n->n_left); sp[i]->sflags |= STNODE; ecomp(n); } }
static NODE * builtin_va_arg(const struct bitable *bt, NODE *a) { NODE *p, *q, *r, *rv; int sz, nodnum; /* create a copy to a temp node of current ap */ p = ccopy(a->n_left); q = tempnode(0, p->n_type, p->n_df, p->n_ap); nodnum = regno(q); rv = buildtree(ASSIGN, q, p); r = a->n_right; sz = (int)tsize(r->n_type, r->n_df, r->n_ap)/SZCHAR; /* add one to ap */ #ifdef BACKAUTO rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz))); #else #error fix wrong eval order in builtin_va_arg ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz))); #endif nfree(a->n_right); nfree(a); r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_ap); return buildtree(COMOP, rv, buildtree(UMUL, r, NIL)); }
/* * code for the end of a function * deals with struct return here */ void efcode(void) { NODE *p, *q; int tempnr; int ty; if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) return; ty = cftnsp->stype - FTN; q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); q->n_rval = V0; p = tempnode(0, INCREF(ty), 0, cftnsp->sap); tempnr = regno(p); p = buildtree(ASSIGN, p, q); ecomp(p); q = tempnode(tempnr, INCREF(ty), 0, cftnsp->sap); q = buildtree(UMUL, q, NIL); p = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); p = buildtree(UMUL, p, NIL); p = buildtree(ASSIGN, p, q); ecomp(p); q = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); p->n_rval = V0; p = buildtree(ASSIGN, p, q); ecomp(p); }
/* called by moveargs() */ static NODE * pusharg(NODE *p, int *regp) { NODE *q; int sz; /* convert to register size, if smaller */ sz = tsize(p->n_type, p->n_df, p->n_ap); if (sz < SZINT) p = block(SCONV, p, NIL, INT, 0, 0); q = block(REG, NIL, NIL, INT, 0, 0); regno(q) = SP; if (szty(p->n_type) == 1) { ++(*regp); q = block(MINUSEQ, q, bcon(4), INT, 0, 0); } else { (*regp) += 2; q = block(MINUSEQ, q, bcon(8), INT, 0, 0); } q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_ap); return buildtree(ASSIGN, q, p); }
/* setup a 32-bit param on the stack * used by bfcode() */ static void param_32bit(struct symtab *sym, int *argofsp, int dotemps) { NODE *p, *q; q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); regno(q) = R0 + (*argofsp)++; if (dotemps) { p = tempnode(0, sym->stype, sym->sdf, sym->sap); sym->soffset = regno(p); sym->sflags |= STNODE; } else { p = nametree(sym); } p = buildtree(ASSIGN, p, q); ecomp(p); }
void bfcode(struct symtab **sp, int n) { struct symtab *sp2; NODE *p, *q; int i, argbase, sz; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Move return address into temporary */ p = tempnode(0, INT, 0, 0); strtemp = regno(p); q = block(REG, 0, 0, INT, 0, 0); regno(q) = R1; ecomp(buildtree(ASSIGN, p, q)); } /* correct arg alignment XXX should be done somewhere else */ argbase = ARGINIT; for (i = 0; i < n; i++) { sp2 = sp[i]; sz = tsize(sp2->stype, sp2->sdf, sp2->sap); SETOFF(sz, SZINT); sp2->soffset = argbase; argbase += sz; } if (xtemps == 0) return; /* put arguments in temporaries */ for (i = 0; i < n; i++) { if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || cisreg(sp[i]->stype) == 0) continue; if (cqual(sp[i]->stype, sp[i]->squal) & VOL) continue; sp2 = sp[i]; p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); p = buildtree(ASSIGN, p, nametree(sp2)); sp[i]->soffset = regno(p->n_left); sp[i]->sflags |= STNODE; ecomp(p); } }
/* called from moveargs() */ static NODE * movearg_float(NODE *p, int *regp) { NODE *q, *r; TWORD ty = INCREF(p->n_type); int tmpnr; /* * Floats are passed in the general registers for * compatibily with libraries compiled to handle soft-float. */ if (xtemps) { /* bounce on TOS */ r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); regno(r) = SP; r = block(PLUS, r, bcon(-4), ty, p->n_df, p->n_ap); r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); r = buildtree(ASSIGN, r, p); ecomp(r); /* bounce into temp */ r = block(REG, NIL, NIL, PTR+INT, 0, 0); regno(r) = SP; r = block(PLUS, r, bcon(-8), PTR+INT, 0, 0); r = block(UMUL, r, NIL, INT, 0, 0); q = tempnode(0, INT, 0, 0); tmpnr = regno(q); r = buildtree(ASSIGN, q, r); ecomp(r); } else { /* copy directly into temp */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); r = buildtree(ASSIGN, q, p); ecomp(r); } /* copy from temp to register parameter */ r = tempnode(tmpnr, INT, 0, 0); q = block(REG, NIL, NIL, INT, 0, 0); regno(q) = (*regp)++; p = buildtree(ASSIGN, q, r); return p; }
static NODE * movtoreg(NODE *p, int rno) { NODE *r; r = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); regno(r) = rno; return clocal(buildtree(ASSIGN, r, p)); }
static NODE * mkstkref(int off, TWORD typ) { NODE *p; p = block(REG, NIL, NIL, PTR|typ, 0, MKAP(LONG)); regno(p) = FPREG; return buildtree(PLUS, p, bcon(off/SZCHAR)); }
/* * code for the beginning of a function; 'a' is an array of * indices in symtab for the arguments; n is the number */ void bfcode(struct symtab **a, int cnt) { struct symtab *sp; NODE *p, *q; int i, n, sz; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Function returns struct, adjust arg offset */ for (i = 0; i < n; i++) a[i]->soffset += SZPOINT(LONG); } /* recalculate the arg offset and create TEMP moves */ for (n = 0, i = 0; i < cnt; i++) { sp = a[i]; sz = szty(sp->stype); if (n % sz) n++; /* XXX LDOUBLE */ if (n < 4) { p = tempnode(0, sp->stype, sp->sdf, sp->ssue); /* TODO p->n_left->n_lval = -(32 + n * 4); */ q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue); q->n_rval = argreg(sp->stype, &n); p = buildtree(ASSIGN, p, q); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } else { sp->soffset += SZINT * n; if (xtemps) { /* put stack args in temps if optimizing */ p = tempnode(0, sp->stype, sp->sdf, sp->ssue); p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } } } }
/* Put a symbol in a temporary * used by bfcode() and its helpers */ static void putintemp(struct symtab *sym) { NODE *p; p = tempnode(0, sym->stype, sym->sdf, sym->sap); p = buildtree(ASSIGN, p, nametree(sym)); sym->soffset = regno(p->n_left); sym->sflags |= STNODE; ecomp(p); }
/* called from moveargs() */ static NODE * movearg_double(NODE *p, int *regp) { NODE *q, *r; TWORD ty = INCREF(p->n_type); int tmpnr; if (xtemps) { /* bounce on TOS */ r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); regno(r) = SP; r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_ap); r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); r = buildtree(ASSIGN, r, p); ecomp(r); /* bounce into temp */ r = block(REG, NIL, NIL, PTR+LONGLONG, 0, 0); regno(r) = SP; r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, 0); r = block(UMUL, r, NIL, LONGLONG, 0, 0); q = tempnode(0, LONGLONG, 0, 0); tmpnr = regno(q); r = buildtree(ASSIGN, q, r); ecomp(r); } else { /* copy directly into temp */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); r = buildtree(ASSIGN, q, p); ecomp(r); } /* copy from temp to register parameter */ r = tempnode(tmpnr, LONGLONG, 0, 0); q = block(REG, NIL, NIL, LONGLONG, 0, 0); regno(q) = R0R1 - R0 + (*regp); p = buildtree(ASSIGN, q, r); (*regp) += 2; return p; }
NODE * mips_builtin_va_arg(NODE *f, NODE *a, TWORD t) { NODE *p, *q, *r; int sz, tmpnr; /* check num args and type */ if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE) goto bad; r = a->n_right; /* get type size */ sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR; if (sz < SZINT/SZCHAR) { werror("%s%s promoted to int when passed through ...", r->n_type & 1 ? "unsigned " : "", DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); sz = SZINT/SZCHAR; } /* alignment */ p = tcopy(a->n_left); if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { p = buildtree(PLUS, p, bcon(7)); p = block(AND, p, bcon(-8), p->n_type, p->n_df, p->n_ap); } /* create a copy to a temp node */ q = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(q); p = buildtree(ASSIGN, q, p); q = tempnode(tmpnr, p->n_type, p->n_df,p->n_ap); q = buildtree(PLUS, q, bcon(sz)); q = buildtree(ASSIGN, a->n_left, q); q = buildtree(COMOP, p, q); nfree(a->n_right); nfree(a); nfree(f); p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap); p = buildtree(UMUL, p, NIL); p = buildtree(COMOP, q, p); return p; bad: uerror("bad argument to __builtin_va_arg"); return bcon(0); }
/* * set registers in calling conventions live. */ int * livecall(NODE *p) { static int r[NTEMPREG+1]; NODE *q; int cr = 0; if (optype(p->n_op) != BITYPE) return r[0] = -1, r; for (q = p->n_right; q->n_op == CM; q = q->n_left) { if (q->n_right->n_op == ASSIGN && q->n_right->n_left->n_op == REG) r[cr++] = regno(q->n_right->n_left); } if (q->n_op == ASSIGN && q->n_left->n_op == REG) r[cr++] = regno(q->n_left); r[cr++] = -1; return r; }
/* setup the hidden pointer to struct return parameter * used by bfcode() */ static void param_retptr(void) { NODE *p, *q; p = tempnode(0, PTR+STRTY, 0, cftnsp->sap); rvnr = regno(p); q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap); q->n_rval = A0; p = buildtree(ASSIGN, p, q); ecomp(p); }
static void starg(NODE *p) { int sz = p->n_stsize; int subsz = (p->n_stsize + 3) & ~3; int fr, tr, cr; fr = regno(getlr(p, 'L')); /* from reg (struct pointer) */ cr = regno(getlr(p, '1')); /* count reg (number of words) */ tr = regno(getlr(p, '2')); /* to reg (stack) */ /* Sub from stack and put in toreg */ printf(" sub.l #%d,%%sp\n", subsz); printf(" move.l %%sp,%s\n", rnames[tr]); /* Gen an even copy start */ if (sz & 1) expand(p, INBREG, " move.b (A2)+,(AL)+\n"); if (sz & 2) expand(p, INBREG, " move.w (A2)+,(AL)+\n"); sz -= (sz & ~3); /* if more than 4 words, use loop, otherwise output instructions */ if (sz > 16) { printf(" move.l #%d,%s\n", sz/4, rnames[cr]); expand(p, INBREG, "1: move.l (A2)+,(AL)+\n"); expand(p, INBREG, " dec.l A1\n"); expand(p, INBREG, " jne 1b\n"); } else { if (sz > 12) expand(p, INBREG, " move.l (A2)+,(AL)+\n"), sz -= 4; if (sz > 8) expand(p, INBREG, " move.l (A2)+,(AL)+\n"), sz -= 4; if (sz > 4) expand(p, INBREG, " move.l (A2)+,(AL)+\n"), sz -= 4; if (sz == 4) expand(p, INBREG, " move.l (A2)+,(AL)+\n"); } }
/* called from moveargs() */ static NODE * movearg_32bit(NODE *p, int *regp) { int reg = *regp; NODE *q; q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); regno(q) = reg++; q = buildtree(ASSIGN, q, p); *regp = reg; return q; }
/* * Take integer absolute value. * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1))) */ static NODE * builtin_abs(NODE *f, NODE *a, TWORD rt) { NODE *p, *q, *r, *t, *t2, *t3; int tmp1, tmp2, shift; if (a->n_type != INT) a = cast(a, INT, 0); tfree(f); if (a->n_op == ICON) { if (a->n_lval < 0) a->n_lval = -a->n_lval; p = a; } else { t = tempnode(0, a->n_type, a->n_df, a->n_ap); tmp1 = regno(t); p = buildtree(ASSIGN, t, a); t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); shift = (int)tsize(a->n_type, a->n_df, a->n_ap) - 1; q = buildtree(RS, t, bcon(shift)); t2 = tempnode(0, a->n_type, a->n_df, a->n_ap); tmp2 = regno(t2); q = buildtree(ASSIGN, t2, q); t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); t2 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); t3 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); r = buildtree(MINUS, buildtree(ER, t, t2), t3); p = buildtree(COMOP, p, buildtree(COMOP, q, r)); } return p; }
/* * replace an alloca function with direct allocation on stack. * return a destination temp node. */ static NODE * builtin_alloca(const struct bitable *bt, NODE *a) { NODE *t, *u; #ifdef notyet if (xnobuiltins) return NULL; #endif t = tempnode(0, VOID|PTR, 0, 0); u = tempnode(regno(t), VOID|PTR, 0, 0); spalloc(t, a, SZCHAR); return u; }
/* * Take integer absolute value. * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1))) */ static NODE * builtin_abs(const struct bitable *bt, NODE *a) { NODE *p, *q, *r, *t, *t2, *t3; int tmp1, tmp2, shift; if (a->n_type != INT) a = cast(a, INT, 0); if (a->n_op == ICON) { if (getlval(a) < 0) setlval(a, -getlval(a)); p = a; } else { t = tempnode(0, a->n_type, a->n_df, a->n_ap); tmp1 = regno(t); p = buildtree(ASSIGN, t, a); t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); shift = (int)tsize(a->n_type, a->n_df, a->n_ap) - 1; q = buildtree(RS, t, bcon(shift)); t2 = tempnode(0, a->n_type, a->n_df, a->n_ap); tmp2 = regno(t2); q = buildtree(ASSIGN, t2, q); t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); t2 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); t3 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); r = buildtree(MINUS, buildtree(ER, t, t2), t3); p = buildtree(COMOP, p, buildtree(COMOP, q, r)); } return p; }