diff options
62 files changed, 8673 insertions, 3678 deletions
diff --git a/usr.bin/pcc/arm/code.c b/usr.bin/pcc/arm/code.c index 006f62d1a8e..4929b2ef0fb 100644 --- a/usr.bin/pcc/arm/code.c +++ b/usr.bin/pcc/arm/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.2 2007/12/22 12:38:56 stefan Exp $ */ +/* $OpenBSD: code.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -36,46 +36,311 @@ #include "pass1.h" #include "pass2.h" +int lastloc = -1; /* - * Modify the alignment in the data section to become a multiple of n. + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. */ void -defalign(int n) +defloc(struct symtab *sp) { - n /= SZCHAR; - if (n == 1) + extern char *nextsect; + static char *loctbl[] = { "text", "data", "section .rodata" }; + TWORD t; + int s; + + if (sp == NULL) { + lastloc = -1; return; - printf("\t.align %d\n", n); + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? PROG : DATA; + if (nextsect) { + printf("\t.section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf("\t.%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + if (t > UCHAR) + printf("\t.align %d\n", t > USHORT ? 4 : 2); +#ifdef USE_GAS + if (ISFTN(t)) + printf("\t.type %s,%%function\n", exname(sp->soname)); +#endif + if (sp->sclass == EXTDEF) + printf("\t.global %s\n", exname(sp->soname)); + if (ISFTN(t)) + return; + if (sp->slevel == 0) + printf("%s:\n", exname(sp->soname)); + else + printf(LABFMT ":\n", sp->soffset); } -/* - * Define the current location as an internal label. +/* Put a symbol in a temporary + * used by bfcode() and its helpers */ -void -deflab(int label) +static void +putintemp(struct symtab *sym) { - printf(LABFMT ":\n", label); + NODE *p; + + spname = sym; + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); } -/* - * Define the current location in the data section to be the name p->sname - */ -void -defnam(struct symtab *p) +/* setup a 64-bit parameter (double/ldouble/longlong) + * used by bfcode() */ +static void +param_64bit(struct symtab *sym, int *argoffp, int dotemps) { - char *c = p->sname; + int argoff = *argoffp; + NODE *p, *q; + int navail; -#ifdef GCC_COMPAT - c = gcc_findname(p); +#if ALLONGLONG == 64 + /* alignment */ + ++argoff; + argoff &= ~1; + *argoffp = argoff; #endif - if (p->sclass == EXTDEF) - printf("\t.global %s\n", exname(c)); - printf("%s:\n", exname(c)); + + navail = NARGREGS - argoff; + + if (navail < 2) { + /* half in and half out of the registers */ + if (features(FEATURE_BIGENDIAN)) { + cerror("movearg_64bit"); + p = q = NULL; + } else { + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0 + argoff; + if (dotemps) { + q = block(SCONV, q, NIL, + ULONGLONG, 0, MKSUE(ULONGLONG)); + spname = sym; + p = buildtree(NAME, 0, 0); + p->n_type = ULONGLONG; + p->n_df = 0; + p->n_sue = MKSUE(ULONGLONG); + p = block(LS, p, bcon(32), ULONGLONG, + 0, MKSUE(ULONGLONG)); + q = block(PLUS, p, q, ULONGLONG, + 0, MKSUE(ULONGLONG)); + p = tempnode(0, ULONGLONG, + 0, MKSUE(ULONGLONG)); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + spname = sym; + p = buildtree(NAME, 0, 0); + regno(p) = sym->soffset; + p->n_type = INT; + p->n_df = 0; + p->n_sue = MKSUE(INT); + } + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argoffp = argoff + 2; + return; + } + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R0R1 + argoff; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + spname = sym; + p = buildtree(NAME, 0, 0); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argoffp = argoff + 2; +} + +/* setup a 32-bit param on the stack + * used by bfcode() */ +static void +param_32bit(struct symtab *sym, int *argoffp, int dotemps) +{ + NODE *p, *q; + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R0 + (*argoffp)++; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + spname = sym; + p = buildtree(NAME, 0, 0); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* setup a double param on the stack + * used by bfcode() */ +static void +param_double(struct symtab *sym, int *argoffp, 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, ULONGLONG, 0, MKSUE(ULONGLONG)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + q->n_rval = R0R1 + (*argoffp)++; + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue); + spname = sym; + p = buildtree(NAME, 0, 0); + 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 *argoffp, 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, MKSUE(INT)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + q->n_rval = R0 + (*argoffp)++; + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue); + spname = sym; + p = buildtree(NAME, 0, 0); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } } int rvnr; /* + * Beginning-of-function code: + * + * 'sp' is an array of indices in symtab for the arguments + * 'cnt' is the number of arguments + */ +void +bfcode(struct symtab **sp, int cnt) +{ + NODE *p, *q; + union arglist *usym; + int saveallargs = 0; + int i, argoff = 0; + + /* + * Detect if this function has ellipses and save all + * argument registers onto stack. + */ + usym = cftnsp->sdf->dfun; + while (usym && usym->type != TNULL) { + if (usym->type == TELLIPSIS) { + saveallargs = 1; + break; + } + ++usym; + } + + /* if returning a structure, more the hidden argument into a TEMP */ + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); + rvnr = regno(p); + q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + q->n_rval = R0 + argoff++; + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + /* recalculate the arg offset and create TEMP moves */ + for (i = 0; i < cnt; i++) { + + if ((argoff >= NARGREGS) && !xtemps) { + break; + } else if (argoff > NARGREGS) { + putintemp(sp[i]); + } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) { + cerror("unimplemented structure arguments"); + } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) { + param_64bit(sp[i], &argoff, xtemps && !saveallargs); + } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + param_double(sp[i], &argoff, + xtemps && !saveallargs); + else + param_64bit(sp[i], &argoff, + xtemps && !saveallargs); + } else if (sp[i]->stype == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + param_float(sp[i], &argoff, + xtemps && !saveallargs); + else + param_32bit(sp[i], &argoff, + xtemps && !saveallargs); + } else { + param_32bit(sp[i], &argoff, xtemps && !saveallargs); + } + } + + /* if saveallargs, save the rest of the args onto the stack */ + while (saveallargs && argoff < NARGREGS) { + NODE *p, *q; + int off = ARGINIT/SZINT + argoff; + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0 + argoff++; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(4*off), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + +} + +/* * End-of-Function code: */ void @@ -98,7 +363,7 @@ efcode() q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); q->n_rval = R0; p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); - tempnr = p->n_lval; + tempnr = regno(p); p = buildtree(ASSIGN, p, q); ecomp(p); @@ -116,61 +381,6 @@ efcode() } /* - * Beginning-of-function code: - * - * 'a' is an array of indices in symtab for the arguments - * 'n' is the number of arguments - */ -void -bfcode(struct symtab **sp, int cnt) -{ - NODE *p, *q; - int i, n, start = 0; - - /* if returning a structure, more the hidden argument into a TEMP */ - if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { - p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); - rvnr = p->n_lval; - q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); - q->n_rval = R0 + start++; - p = buildtree(ASSIGN, p, q); - ecomp(p); - } - - /* recalculate the arg offset and create TEMP moves */ - for (n = start, i = 0; i < cnt; i++) { - int sz = szty(sp[i]->stype); - if (n + sz <= 4) { - /* put stack args in temps */ - p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); - spname = sp[i]; - q = block(REG, NIL, NIL, - sp[i]->stype, sp[i]->sdf, sp[i]->ssue); - q->n_rval = (sz == 2 ? R0R1 + n : R0+n); - p = buildtree(ASSIGN, p, q); - sp[i]->soffset = p->n_left->n_lval; - sp[i]->sflags |= STNODE; - ecomp(p); - } else { - sp[i]->soffset -= SZINT * 4; - if (xtemps) { - /* put stack args in temps if optimizing */ - spname = sp[i]; - p = tempnode(0, sp[i]->stype, - sp[i]->sdf, sp[i]->ssue); - p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); - sp[i]->soffset = p->n_left->n_lval; - sp[i]->sflags |= STNODE; - ecomp(p); - } - - } - n += szty(sp[i]->stype); - } -} - - -/* * Beginning-of-code: finished generating function prologue * * by now, the automatics and register variables are allocated @@ -189,7 +399,7 @@ ejobcode(int flag ) { #define OSB(x) __STRING(x) #define OS OSB(TARGOS) - printf("\t.ident \"%s (%s)\"\n", PACKAGE_STRING, OS); + printf("\t.ident \"%s (%s)\"\n", VERSSTR, OS); } /* @@ -203,39 +413,6 @@ bjobcode() } /* - * Output ascii string: print character 't' at position 'i' until 't' == -1. - */ -void -bycode(int t, int i) -{ - static int lastoctal = 0; - - /* put byte i+1 in a string */ - - if (t < 0) { - if (i != 0) - puts("\""); - } else { - if (i == 0) - printf("\t.ascii \""); - if (t == '\\' || t == '"') { - lastoctal = 0; - putchar('\\'); - putchar(t); - } else if (t < 040 || t >= 0177) { - lastoctal++; - printf("\\%o",t); - } else if (lastoctal && '0' <= t && t <= '9') { - lastoctal = 0; - printf("\"\n\t.ascii \"%c", t); - } else { - lastoctal = 0; - putchar(t); - } - } -} - -/* * Compute the alignment of object with type 't'. */ int @@ -265,171 +442,183 @@ mygenswitch(int num, TWORD type, struct swents **p, int n) return 0; } -static int regoff[7]; -static TWORD ftype; /* - * calculate stack size and offsets + * Straighten a chain of CM ops so that the CM nodes + * only appear on the left node. + * + * CM CM + * CM CM CM b + * x y a b CM a + * x y */ -static int -offcalc(struct interpass_prolog *ipp) +static NODE * +straighten(NODE *p) { - int i, j, addto; + NODE *r = p->n_right; -#ifdef PCC_DEBUG - if (x2debug) - printf("offcalc: p2maxautooff=%d\n", p2maxautooff); -#endif + if (p->n_op != CM || r->n_op != CM) + return p; - addto = p2maxautooff; + p->n_right = r->n_left; + r->n_left = p; - // space is always allocated on the stack to save the permanents - for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) { - if (i & 1) { - addto += SZINT/SZCHAR; - regoff[j] = addto; - } - } + return r; +} -#if 0 - addto += 7; - addto &= ~7; -#endif -#ifdef PCC_DEBUG - if (x2debug) - printf("offcalc: addto=%d\n", addto); -#endif +/* push arg onto the stack */ +/* called by moveargs() */ +static NODE * +pusharg(NODE *p, int *regp) +{ + NODE *q; + int sz; - addto -= AUTOINIT / SZCHAR; + /* convert to register size, if smaller */ + sz = tsize(p->n_type, p->n_df, p->n_sue); + if (sz < SZINT) + p = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); - return addto; -} + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = SP; -void -prologue(struct interpass_prolog *ipp) -{ - int i, j; - int addto; - -#ifdef PCC_DEBUG - if (x2debug) - printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n", - ipp->ipp_ip.type, - ipp->ipp_ip.lineno, - ipp->ipp_name, - ipp->ipp_vis, - ipp->ipp_type, - ipp->ipp_regs, - ipp->ipp_autos, - ipp->ip_tmpnum, - ipp->ip_lblnum); -#endif + if (szty(p->n_type) == 1) { + ++(*regp); + q = block(MINUSEQ, q, bcon(4), INT, 0, MKSUE(INT)); + } else { + (*regp) += 2; + q = block(MINUSEQ, q, bcon(8), INT, 0, MKSUE(INT)); + } - ftype = ipp->ipp_type; + q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_sue); - printf("\t.align 2\n"); - if (ipp->ipp_vis) - printf("\t.global %s\n", exname(ipp->ipp_name)); - printf("\t.type %s,%%function\n", exname(ipp->ipp_name)); - printf("%s:\n", exname(ipp->ipp_name)); + return buildtree(ASSIGN, q, p); +} - /* - * We here know what register to save and how much to - * add to the stack. - */ - addto = offcalc(ipp); - - printf("\tmov %s,%s\n", rnames[IP], rnames[SP]); - printf("\tstmfd %s!,{%s,%s,%s,%s}\n", rnames[SP], rnames[FP], - rnames[IP], rnames[LR], rnames[PC]); - printf("\tsub %s,%s,#4\n", rnames[FP], rnames[IP]); - if (addto) - printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], addto); - - for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) { - if (i & 1) { - printf("\tstr %s,[%s,#-%d]\n", - rnames[j], rnames[FP], regoff[j]); - } - } +/* setup call stack with 32-bit argument */ +/* 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_sue); + regno(q) = reg++; + q = buildtree(ASSIGN, q, p); + *regp = reg; + return q; } -void -eoftn(struct interpass_prolog *ipp) +/* setup call stack with 64-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_64bit(NODE *p, int *regp) { - int i, j; + int reg = *regp; + NODE *q, *r; + +#if ALLONGLONG == 64 + /* alignment */ + ++reg; + reg &= ~1; + *regp = reg; +#endif - if (ipp->ipp_ip.ip_lbl == 0) - return; /* no code needs to be generated */ + if (reg > R3) { + q = pusharg(p, regp); + } else if (reg == R3) { + /* half in and half out of the registers */ + r = tcopy(p); + if (features(FEATURE_BIGENDIAN)) { + q = buildtree(RS, p, bcon(32)); + q = block(SCONV, q, NIL, INT, 0, MKSUE(INT)); + } else { + q = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); + } + q = movearg_32bit(q, regp); + if (features(FEATURE_BIGENDIAN)) { + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + } else { + r = buildtree(RS, r, bcon(32)); + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + } + r = pusharg(r, regp); + q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_sue)); + } else { + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + regno(q) = R0R1 + (reg - R0); + q = buildtree(ASSIGN, q, p); + *regp = reg + 2; + } - /* return from function code */ - for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) { - if (i & 1) - printf("\tldr %s,[%s,#-%d]\n", - rnames[j], rnames[FP], regoff[j]); - - } + return q; +} - /* struct return needs special treatment */ - if (ftype == STRTY || ftype == UNIONTY) { - assert(0); +/* setup call stack with float/double argument */ +/* called from moveargs() */ +static NODE * +movearg_float(NODE *p, int *regp) +{ + NODE *r, *l; + int tmpnr; + + /* + * Floats are passed in the general registers for + * compatibily with libraries compiled to handle soft-float. + */ + + l = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(l); + l = buildtree(ASSIGN, l, p); + ecomp(l); + + if (p->n_type == FLOAT) { + r = tempnode(tmpnr, INT, 0, MKSUE(INT)); + r = movearg_32bit(r, regp); } else { - printf("\tldmea %s,{%s,%s,%s}\n", rnames[FP], rnames[FP], - rnames[SP], rnames[PC]); + r = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG)); + r = movearg_64bit(r, regp); } - printf("\t.size %s,.-%s\n", exname(ipp->ipp_name), - exname(ipp->ipp_name)); -} -char *rnames[] = { - "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", "r8", - "r9", "r10", "fp", "ip", "sp", "lr", "pc", - "r0r1", "r1r2", "r2r3", "r3r4", "r4r5", "r5r6", - "r6r7", "r7r8", "r8r9", "r9r10", -}; + return r; +} -static void -moveargs(NODE **n, int *regp) +static NODE * +moveargs(NODE *p, int *regp) { - NODE *r = *n; - NODE *t; - int sz; - int regnum; - - if (r->n_op == CM) { - moveargs(&r->n_left, regp); - n = &r->n_right; - r = r->n_right; + NODE *r, **rp; + 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; } - regnum = *regp; - sz = szty(r->n_type); - - if (regnum + sz <= R4) { - t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue); - switch (r->n_type) { - case DOUBLE: - case LDOUBLE: -#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP) - t->n_rval = regnum + F0; - break; -#endif - case LONGLONG: - case ULONGLONG: - t->n_rval = regnum + R0R1; - break; - default: - t->n_rval = regnum; - } - t = buildtree(ASSIGN, t, r); + reg = *regp; + + if (reg > R3) { + *rp = pusharg(r, regp); + } else if (DEUNSIGN(r->n_type) == LONGLONG) { + *rp = movearg_64bit(r, regp); + } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { + *rp = movearg_float(r, regp); + } else if (r->n_type == FLOAT) { + *rp = movearg_float(r, regp); } else { - t = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue); + *rp = movearg_32bit(r, regp); } - *n = t; - *regp += sz; + if ((*rp)->n_op == CM && r != p) + p = straighten(p); + + return p; } /* @@ -439,13 +628,14 @@ moveargs(NODE **n, int *regp) NODE * funcode(NODE *p) { - int regnum = R0; + int reg = R0; int ty; ty = DECREF(p->n_left->n_type); if (ty == STRTY+FTN || ty == UNIONTY+FTN) - regnum = R1; + reg = R1; + + p->n_right = moveargs(p->n_right, ®); - moveargs(&p->n_right, ®num); return p; } diff --git a/usr.bin/pcc/arm/local.c b/usr.bin/pcc/arm/local.c index 70e9bfb4419..d11a0bdd6a8 100644 --- a/usr.bin/pcc/arm/local.c +++ b/usr.bin/pcc/arm/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.1 2007/11/25 18:45:06 otto Exp $ */ +/* $OpenBSD: local.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -36,6 +36,8 @@ #include "pass1.h" +extern void defalign(int); + /* * clocal() is called to do local transformations on * an expression tree before being sent to the backend. @@ -47,6 +49,7 @@ clocal(NODE *p) NODE *l, *r, *t; int o; int ty; + int tmpnr, isptrvoid = 0; o = p->n_op; switch (o) { @@ -55,28 +58,53 @@ clocal(NODE *p) l = p->n_left; r = p->n_right; - if (r->n_op == STCALL || r->n_op == USTCALL) { - /* assign left node as first argument to function */ - nfree(p); - t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue); - l->n_rval = R0; - l = buildtree(ADDROF, l, NIL); - l = buildtree(ASSIGN, t, l); - ecomp(l); - t = tempnode(0, r->n_type, r->n_df, r->n_sue); - r = buildtree(ASSIGN, t, r); - ecomp(r); - t = tempnode(t->n_lval, r->n_type, r->n_df, r->n_sue); - return t; + if (r->n_op != STCALL && r->n_op != USTCALL) + return p; + + /* assign left node as first argument to function */ + nfree(p); + t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue); + l->n_rval = R0; + l = buildtree(ADDROF, l, NIL); + l = buildtree(ASSIGN, t, l); + + if (r->n_right->n_op != CM) { + r->n_right = block(CM, l, r->n_right, + INT, 0, MKSUE(INT)); + } else { + for (t = r->n_right; t->n_left->n_op == CM; + t = t->n_left) + ; + t->n_left = block(CM, l, t->n_left, + INT, 0, MKSUE(INT)); } - break; + return r; -#if 0 case CALL: + case STCALL: + case USTCALL: + if (p->n_type == VOID) + break; + /* + * if the function returns void*, ecode() invokes + * delvoid() to convert it to uchar*. + * We just let this happen on the ASSIGN to the temp, + * and cast the pointer back to void* on access + * from the temp. + */ + if (p->n_type == PTR+VOID) + isptrvoid = 1; r = tempnode(0, p->n_type, p->n_df, p->n_sue); - ecomp(buildtree(ASSIGN, r, p)); - return r; -#endif + tmpnr = regno(r); + r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_sue); + + p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); + if (isptrvoid) { + p = block(PCONV, p, NIL, PTR+VOID, + p->n_df, MKSUE(PTR+VOID)); + } + p = buildtree(COMOP, r, p); + break; case NAME: if ((q = p->n_sp) == NULL) @@ -100,12 +128,14 @@ clocal(NODE *p) break; case STATIC: if (q->slevel > 0) { - p->n_lval = 0; - p->n_sp = q; - } - break; + p->n_lval = 0; + p->n_sp = q; + } + /* FALL-THROUGH */ default: ty = p->n_type; + if (strncmp(p->n_sp->soname, "__builtin", 9) == 0) + break; p = block(ADDROF, p, NIL, INCREF(ty), p->n_df, p->n_sue); p = block(UMUL, p, NIL, ty, p->n_df, p->n_sue); break; @@ -157,15 +187,6 @@ clocal(NODE *p) } } -#if 0 // table.c will handle these okay - if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && - coptype(l->n_op) == BITYPE) { - l->n_type = p->n_type; - nfree(p); - return l; - } -#endif - if (l->n_op == ICON) { CONSZ val = l->n_lval; @@ -215,14 +236,15 @@ clocal(NODE *p) l->n_sue = MKSUE(p->n_type); nfree(p); return l; - } -#if 0 // table.c will handle these okay - if (DEUNSIGN(p->n_type) == SHORT && - DEUNSIGN(l->n_type) == SHORT) { - nfree(p); - p = l; - } -#endif + } else if (p->n_op == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = p->n_type; + l->n_sue = MKSUE(p->n_type); + nfree(p); + return clocal(l); + } if ((DEUNSIGN(p->n_type) == CHAR || DEUNSIGN(p->n_type) == SHORT) && (l->n_type == FLOAT || l->n_type == DOUBLE || @@ -271,6 +293,29 @@ clocal(NODE *p) void myp2tree(NODE *p) { + struct symtab *sp; + + if (p->n_op != FCON) + return; + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + } /* @@ -349,6 +394,57 @@ spalloc(NODE *t, NODE *p, OFFSZ off) ecomp(buildtree(ASSIGN, t, sp)); } +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +/* + * Print out a wide string by calling ninval(). + */ +void +inwstring(struct symtab *sp) +{ + char *s = sp->sname; + NODE *p; + + defloc(sp); + p = bcon(0); + do { + if (*s++ == '\\') + p->n_lval = esccon(&s); + else + p->n_lval = (unsigned char)s[-1]; + ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p); + } while (s[-1] != 0); + nfree(p); +} + + static int inbits = 0, inval = 0; /* @@ -423,8 +519,18 @@ ninval(CONSZ off, int fsz, NODE *p) if (t > BTMASK) t = INT; /* pointer */ + /* + * The target-independent code does rewrite the NAME nodes + * to ICONS after we prefixed the NAME nodes with ADDROF. + * We do it here. Maybe this is too much of a hack! + */ + if (p->n_op == ADDROF && p->n_left->n_op == NAME) { + p = p->n_left; + p->n_op = ICON; + } + if (p->n_op != ICON && p->n_op != FCON) - cerror("ninval: init node not constant"); + cerror("ninval: init node not constant: node %p", p); if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) uerror("element not constant"); @@ -435,17 +541,17 @@ ninval(CONSZ off, int fsz, NODE *p) i = (p->n_lval >> 32); j = (p->n_lval & 0xffffffff); p->n_type = INT; -#ifdef TARGET_BIG_ENDIAN - p->n_lval = i; - ninval(off+32, 32, p); - p->n_lval = j; - ninval(off, 32, p); -#else - p->n_lval = j; - ninval(off, 32, p); - p->n_lval = i; - ninval(off+32, 32, p); -#endif + if (features(FEATURE_BIGENDIAN)) { + p->n_lval = i; + ninval(off+32, 32, p); + p->n_lval = j; + ninval(off, 32, p); + } else { + p->n_lval = j; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + } break; case INT: case UNSIGNED: @@ -455,7 +561,7 @@ ninval(CONSZ off, int fsz, NODE *p) q->sclass == ILABEL) { printf("+" LABFMT, q->soffset); } else - printf("+%s", exname(q->sname)); + printf("+%s", exname(q->soname)); } printf("\n"); break; @@ -474,12 +580,16 @@ ninval(CONSZ off, int fsz, NODE *p) case LDOUBLE: case DOUBLE: u.d = (double)p->n_dcon; -#if (defined(TARGET_BIG_ENDIAN) && defined(HOST_LITTLE_ENDIAN)) || \ - (defined(TARGET_LITTLE_ENDIAN) && defined(HOST_BIG_ENDIAN)) - printf("\t.word\t0x%x\n\t.word\t0x%x\n", u.i[0], u.i[1]); +#if defined(HOST_BIG_ENDIAN) + if (features(FEATURE_BIGENDIAN)) #else - printf("\t.word\t0x%x\n\t.word\t0x%x\n", u.i[1], u.i[0]); + if (!features(FEATURE_BIGENDIAN)) #endif + printf("\t.word\t0x%x\n\t.word\t0x%x\n", + u.i[0], u.i[1]); + else + printf("\t.word\t0x%x\n\t.word\t0x%x\n", + u.i[1], u.i[0]); break; case FLOAT: u.f = (float)p->n_dcon; @@ -535,61 +645,19 @@ extdec(struct symtab *q) { } -/* - * make a common declaration for 'id', if reasonable - */ +/* make a common declaration for id, if reasonable */ void -commdec(struct symtab *q) +defzero(struct symtab *sp) { int off; - off = tsize(q->stype, q->sdf, q->ssue); + off = tsize(sp->stype, sp->sdf, sp->ssue); off = (off+(SZCHAR-1))/SZCHAR; -#ifdef GCC_COMPAT - printf("\t.comm %s,%d,%d\n", exname(gcc_findname(q)), off, 4); -#else - printf("\t.comm %s,%,%d\n", exname(q->sname), off, 4); -#endif -} - -/* - * make a local common declaration for 'id', if reasonable - */ -void -lcommdec(struct symtab *q) -{ - int off; - - off = tsize(q->stype, q->sdf, q->ssue); - off = (off+(SZCHAR-1))/SZCHAR; - if (q->slevel == 0) -#ifdef GCC_COMPAT - printf("\t.lcomm %s,%d\n", exname(gcc_findname(q)), off); -#else - printf("\t.lcomm %s,%d\n", exname(q->sname), off); -#endif + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", exname(sp->soname), off); else - printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off); -} - -/* - * Print a (non-prog) label. - */ -void -deflab1(int label) -{ - printf(LABFMT ":\n", label); -} - -static char *loctbl[] = { "text", "data", "text", "section .rodata" }; - -void -setloc1(int locc) -{ - if (locc == lastloc) - return; - lastloc = locc; - printf("\t.%s\n", loctbl[locc]); + printf(LABFMT ",0%o\n", sp->soffset, off); } /* @@ -603,38 +671,137 @@ setloc1(int locc) NODE * arm_builtin_stdarg_start(NODE *f, NODE *a) { - NODE *p; - int sz = 1; - - /* check num args and type */ - if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || - !ISPTR(a->n_left->n_type)) - goto bad; - - /* must first deal with argument size; use int size */ - p = a->n_right; - if (p->n_type < INT) - sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue); + NODE *p, *q; + int sz = 1; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type)) + goto bad; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + /* round up to word */ + sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue); + } + + p = buildtree(ADDROF, p, NIL); /* address of last arg */ + p = optim(buildtree(PLUS, p, bcon(sz))); + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); + tfree(f); + nfree(a); + + return p; bad: - return bcon(0); + uerror("bad argument to __builtin_stdarg_start"); + return bcon(0); } NODE * arm_builtin_va_arg(NODE *f, NODE *a) { - return bcon(0); + 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_sue) / SZCHAR; + if (sz < SZINT/SZCHAR) { + werror("%s%s promoted to int when passed through ...", + ISUNSIGNED(r->n_type) ? "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(ALSTACK/8 - 1)); + p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_sue); + } + + /* create a copy to a temp node */ + q = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(q); + p = buildtree(ASSIGN, q, p); + + q = tempnode(tmpnr, p->n_type, p->n_df,p->n_sue); + 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_sue); + p = buildtree(UMUL, p, NIL); + p = buildtree(COMOP, q, p); + + return p; + +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); } NODE * arm_builtin_va_end(NODE *f, NODE *a) { + tfree(f); + tfree(a); + return bcon(0); } NODE * arm_builtin_va_copy(NODE *f, NODE *a) { - return bcon(0); + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM) + goto bad; + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; + +bad: + uerror("bad argument to __buildtin_va_copy"); + return bcon(0); +} + +char *nextsect; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char **ary) +{ + if (strcmp(ary[1], "section") || ary[2] == NULL) + return 0; + nextsect = newstring(ary[2], strlen(ary[2])); + return 1; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ } diff --git a/usr.bin/pcc/arm/local2.c b/usr.bin/pcc/arm/local2.c index 36182094d41..8d68f59c338 100644 --- a/usr.bin/pcc/arm/local2.c +++ b/usr.bin/pcc/arm/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.3 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -32,9 +32,203 @@ #include <string.h> #include <stdlib.h> -#include "pass1.h" #include "pass2.h" +extern void defalign(int); + +#define exname(x) x + +char *rnames[] = { + "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", + "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", + "r0r1", "r1r2", "r2r3", "r3r4", "r4r5", "r5r6", + "r6r7", "r7r8", "r8r9", "r9r10", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", +}; + +/* + * Handling of integer constants. We have 8 bits + an even + * number of rotates available as a simple immediate. + * If a constant isn't trivially representable, use an ldr + * and a subsequent sequence of orr operations. + */ + +static int +trepresent(const unsigned int val) +{ + int i; +#define rotate_left(v, n) (v << n | v >> (32 - n)) + + for (i = 0; i < 32; i += 2) + if (rotate_left(val, i) <= 0xff) + return 1; + return 0; +} + +/* + * Return values are: + * 0 - output constant as is (should be covered by trepresent() above) + * 1 - 4 generate 1-4 instructions as needed. + */ +static int +encode_constant(int constant, int *values) +{ + int tmp = constant; + int i = 0; + int first_bit, value; + + while (tmp) { + first_bit = ffs(tmp); + first_bit -= 1; /* ffs indexes from 1, not 0 */ + first_bit &= ~1; /* must use even bit offsets */ + + value = tmp & (0xff << first_bit); + values[i++] = value; + tmp &= ~value; + } + return i; +} + +#if 0 +static void +load_constant(NODE *p) +{ + int v = p->n_lval & 0xffffffff; + int reg = DECRA(p->n_reg, 1); + + load_constant_into_reg(reg, v); +} +#endif + +static void +load_constant_into_reg(int reg, int v) +{ + if (trepresent(v)) + printf("\tmov %s,#%d\n", rnames[reg], v); + else if (trepresent(-v)) + printf("\tmvn %s,#%d\n", rnames[reg], -v); + else { + int vals[4], nc, i; + + nc = encode_constant(v, vals); + for (i = 0; i < nc; i++) { + if (i == 0) { + printf("\tmov %s,#%d" COM "load constant %d\n", + rnames[reg], vals[i], v); + } else { + printf("\torr %s,%s,#%d\n", + rnames[reg], rnames[reg], vals[i]); + } + } + } +} + +static TWORD ftype; + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int addto; + +#ifdef PCC_DEBUG + if (x2debug) + printf("offcalc: p2maxautooff=%d\n", p2maxautooff); +#endif + + addto = p2maxautooff; + +#if 0 + addto += 7; + addto &= ~7; +#endif + +#ifdef PCC_DEBUG + if (x2debug) + printf("offcalc: addto=%d\n", addto); +#endif + + addto -= AUTOINIT / SZCHAR; + + return addto; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + int vals[4], nc, i; + +#ifdef PCC_DEBUG + if (x2debug) + printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n", + ipp->ipp_ip.type, + ipp->ipp_ip.lineno, + ipp->ipp_name, + ipp->ipp_vis, + ipp->ipp_type, + ipp->ipp_regs, + ipp->ipp_autos, + ipp->ip_tmpnum, + ipp->ip_lblnum); +#endif + + ftype = ipp->ipp_type; + +#if 0 + printf("\t.align 2\n"); + if (ipp->ipp_vis) + printf("\t.global %s\n", exname(ipp->ipp_name)); + printf("\t.type %s,%%function\n", exname(ipp->ipp_name)); +#endif + printf("%s:\n", exname(ipp->ipp_name)); + + /* + * We here know what register to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); + + printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], 16); + printf("\tmov %s,%s\n", rnames[IP], rnames[SP]); + printf("\tstmfd %s!,{%s,%s,%s,%s}\n", rnames[SP], rnames[FP], + rnames[IP], rnames[LR], rnames[PC]); + printf("\tsub %s,%s,#4\n", rnames[FP], rnames[IP]); + + if (addto == 0) + return; + + if (trepresent(addto)) { + printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], addto); + } else { + nc = encode_constant(addto, vals); + for (i = 0; i < nc; i++) + printf("\tsub %s,%s,#%d\n", + rnames[SP], rnames[SP], vals[i]); + } +} + +void +eoftn(struct interpass_prolog *ipp) +{ + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) { + assert(0); + } else { + printf("\tldmea %s,{%s,%s,%s}\n", rnames[FP], rnames[FP], + rnames[SP], rnames[PC]); + printf("\tadd %s,%s,#%d\n", rnames[SP], rnames[SP], 16); + } + printf("\t.size %s,.-%s\n", exname(ipp->ipp_name), + exname(ipp->ipp_name)); +} + + /* * these mnemonics match the order of the preprocessor decls * EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT @@ -161,18 +355,46 @@ twollcomp(NODE *p) } if (p->n_op >= ULE) cb1 += 4, cb2 += 4; - expand(p, 0, "\tcmp UR,UL\t@ compare 64-bit values (upper)\n"); + expand(p, 0, "\tcmp UR,UL" COM "compare 64-bit values (upper)\n"); if (cb1) cbgen(cb1, s); if (cb2) cbgen(cb2, e); - expand(p, 0, "\tcmp AR,AL\t@ (and lower)\n"); + expand(p, 0, "\tcmp AR,AL" COM "(and lower)\n"); cbgen(p->n_op, e); deflab(s); } int -fldexpand(NODE *P, int cookie, char **cp) +fldexpand(NODE *p, int cookie, char **cp) { - return 0; + CONSZ val; + int shft; + + if (p->n_op == ASSIGN) + p = p->n_left; + + if (features(FEATURE_BIGENDIAN)) + shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval); + else + shft = UPKFOFF(p->n_rval); + + switch (**cp) { + case 'S': + printf("#%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("#%d", shft); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= shft; + printf("%lld", (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; } #if 0 @@ -239,11 +461,19 @@ static void stasg(NODE *p) { NODE *l = p->n_left; - - printf("\tldr %s,=%d\n", rnames[R2], p->n_stsize); - if (l->n_rval != R0 || l->n_lval != 0) - printf("\tadd %s,%s," CONFMT "\n", rnames[R0], - rnames[l->n_rval], l->n_lval); + int val = l->n_lval; + + load_constant_into_reg(R2, p->n_stsize); + if (l->n_rval != R0 || l->n_lval != 0) { + if (trepresent(val)) { + printf("\tadd %s,%s,#%d\n", + rnames[R0], rnames[regno(l)], val); + } else { + load_constant_into_reg(R0, val); + printf("\tadd %s,%s,%s\n", rnames[R0], + rnames[R0], rnames[regno(l)]); + } + } printf("\tbl %s\n", exname("memcpy")); } @@ -252,23 +482,26 @@ shiftop(NODE *p) { NODE *r = p->n_right; TWORD ty = p->n_type; + char *shifttype; if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) { expand(p, INBREG, "\tmov A1,AL,lsr "); - printf(CONFMT "\t@ 64-bit left-shift\n", 32 - r->n_lval); + printf(CONFMT COM "64-bit left-shift\n", 32 - r->n_lval); expand(p, INBREG, "\tmov U1,UL,asl AR\n"); expand(p, INBREG, "\torr U1,U1,A1\n"); expand(p, INBREG, "\tmov A1,AL,asl AR\n"); } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) { - expand(p, INBREG, "\tldr A1,=0\t@ 64-bit left-shift\n"); - expand(p, INBREG, "\tmov U1,AL,asl "); - printf(CONFMT "\n", r->n_lval - 32); + expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tmov U1,AL"); + if (r->n_lval - 32 != 0) + printf(",asl " CONFMT, r->n_lval - 32); + printf("\n"); } else if (p->n_op == LS && r->n_op == ICON) { - expand(p, INBREG, "\tldr A1,=0\t@ 64-bit left-shift\n"); - expand(p, INBREG, "\tldr U1,=0\n"); + expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tmov U1,#0\n"); } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) { expand(p, INBREG, "\tmov U1,UL,asl "); - printf(CONFMT "\t@ 64-bit right-shift\n", 32 - r->n_lval); + printf(CONFMT COM "64-bit right-shift\n", 32 - r->n_lval); expand(p, INBREG, "\tmov A1,AL,lsr AR\n"); expand(p, INBREG, "\torr A1,A1,U1\n"); if (ty == LONGLONG) @@ -277,16 +510,20 @@ shiftop(NODE *p) expand(p, INBREG, "\tmov U1,UL,lsr AR\n"); } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) { if (ty == LONGLONG) { - expand(p, INBREG, "\tldr U1,=-1\t@ 64-bit right-shift\n"); - expand(p, INBREG, "\tmov A1,UL,asr "); + expand(p, INBREG, "\tmvn U1,#1" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov A1,UL"); + shifttype = "asr"; }else { - expand(p, INBREG, "\tldr U1,=0\t@ 64-bit right-shift\n"); - expand(p, INBREG, "\tmov A1,UL,lsr "); + expand(p, INBREG, "\tmov U1,#0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov A1,UL"); + shifttype = "lsr"; } - printf(CONFMT "\n", r->n_lval - 32); - } else if (p->n_op == LS && r->n_op == ICON) { - expand(p, INBREG, "\tldr A1,=0\t@ 64-bit right-shift\n"); - expand(p, INBREG, "\tldr U1,=0\n"); + if (r->n_lval - 32 != 0) + printf(",%s " CONFMT, shifttype, r->n_lval - 32); + printf("\n"); + } else if (p->n_op == RS && r->n_op == ICON) { + expand(p, INBREG, "\tmov A1,#0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov U1,#0\n"); } } @@ -301,104 +538,104 @@ fpemul(NODE *p) if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; - else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3"; + else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "adddf3"; else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; - else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3"; + else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subdf3"; else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; - else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3"; + else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "muldf3"; else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; - else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3"; + else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divdf3"; else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; - else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2"; + else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negdf2"; else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; - else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2"; + else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqdf2"; else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; - else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2"; + else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "nedf2"; else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; - else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2"; + else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "gedf2"; else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; - else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2"; + else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "ledf2"; else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; - else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2"; + else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gtdf2"; else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; - else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2"; + else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "ltdf2"; else if (p->n_op == SCONV && p->n_type == FLOAT) { if (l->n_type == DOUBLE) ch = "truncdfsf2"; - else if (l->n_type == LDOUBLE) ch = "trunctfsf2"; - else if (l->n_type == ULONGLONG) ch = "floatuntisf"; - else if (l->n_type == LONGLONG) ch = "floattisf"; - else if (l->n_type == LONG) ch = "floatdisf"; - else if (l->n_type == ULONG) ch = "floatundisf"; + else if (l->n_type == LDOUBLE) ch = "truncdfsf2"; + else if (l->n_type == ULONGLONG) ch = "floatundisf"; + else if (l->n_type == LONGLONG) ch = "floatdisf"; + else if (l->n_type == LONG) ch = "floatsisf"; + else if (l->n_type == ULONG) ch = "floatunsisf"; else if (l->n_type == INT) ch = "floatsisf"; else if (l->n_type == UNSIGNED) ch = "floatunsisf"; } else if (p->n_op == SCONV && p->n_type == DOUBLE) { if (l->n_type == FLOAT) ch = "extendsfdf2"; else if (l->n_type == LDOUBLE) ch = "trunctfdf2"; - else if (l->n_type == ULONGLONG) ch = "floatuntidf"; - else if (l->n_type == LONGLONG) ch = "floattidf"; - else if (l->n_type == LONG) ch = "floatdidf"; - else if (l->n_type == ULONG) ch = "floatundidf"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunsidf"; else if (l->n_type == INT) ch = "floatsidf"; else if (l->n_type == UNSIGNED) ch = "floatunsidf"; } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { - if (l->n_type == FLOAT) ch = "extendsftf2"; - else if (l->n_type == DOUBLE) ch = "extenddftf2"; - else if (l->n_type == ULONGLONG) ch = "floatuntitf"; - else if (l->n_type == LONGLONG) ch = "floattitf"; - else if (l->n_type == LONG) ch = "floatditf"; - else if (l->n_type == ULONG) ch = "floatunsditf"; - else if (l->n_type == INT) ch = "floatsitf"; - else if (l->n_type == UNSIGNED) ch = "floatunsitf"; + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == DOUBLE) ch = "extenddftd2"; + else if (l->n_type == ULONGLONG) ch = "floatundidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunsidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { - if (l->n_type == FLOAT) ch = "fixunssfti"; - else if (l->n_type == DOUBLE) ch = "fixunsdfti"; - else if (l->n_type == LDOUBLE) ch = "fixunstfti"; + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; } else if (p->n_op == SCONV && p->n_type == LONGLONG) { - if (l->n_type == FLOAT) ch = "fixsfti"; - else if (l->n_type == DOUBLE) ch = "fixdfti"; - else if (l->n_type == LDOUBLE) ch = "fixtfti"; - } else if (p->n_op == SCONV && p->n_type == LONG) { if (l->n_type == FLOAT) ch = "fixsfdi"; else if (l->n_type == DOUBLE) ch = "fixdfdi"; - else if (l->n_type == LDOUBLE) ch = "fixtfdi"; + else if (l->n_type == LDOUBLE) ch = "fixdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONG) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; } else if (p->n_op == SCONV && p->n_type == ULONG) { if (l->n_type == FLOAT) ch = "fixunssfdi"; else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; - else if (l->n_type == LDOUBLE) ch = "fixunstfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; } else if (p->n_op == SCONV && p->n_type == INT) { if (l->n_type == FLOAT) ch = "fixsfsi"; else if (l->n_type == DOUBLE) ch = "fixdfsi"; - else if (l->n_type == LDOUBLE) ch = "fixtfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { if (l->n_type == FLOAT) ch = "fixunssfsi"; else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; - else if (l->n_type == LDOUBLE) ch = "fixunstfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; } if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); - printf("\tbl __%s\t@ softfloat operation\n", exname(ch)); + printf("\tbl __%s" COM "softfloat operation\n", exname(ch)); if (p->n_op >= EQ && p->n_op <= GT) printf("\tcmp %s,#0\n", rnames[R0]); @@ -426,23 +663,23 @@ emul(NODE *p) else if (p->n_op == RS && p->n_type == LONG) ch = "ashrdi3"; else if (p->n_op == RS && p->n_type == INT) ch = "ashrsi3"; - else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divti3"; + else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; else if (p->n_op == DIV && p->n_type == LONG) ch = "divdi3"; else if (p->n_op == DIV && p->n_type == INT) ch = "divsi3"; - else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivti3"; + else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; else if (p->n_op == DIV && p->n_type == ULONG) ch = "udivdi3"; else if (p->n_op == DIV && p->n_type == UNSIGNED) ch = "udivsi3"; - else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "modti3"; + else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; else if (p->n_op == MOD && p->n_type == LONG) ch = "moddi3"; else if (p->n_op == MOD && p->n_type == INT) ch = "modsi3"; - else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umodti3"; + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; else if (p->n_op == MOD && p->n_type == ULONG) ch = "umoddi3"; else if (p->n_op == MOD && p->n_type == UNSIGNED) ch = "umodsi3"; - else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "multi3"; + else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; else if (p->n_op == MUL && p->n_type == LONG) ch = "muldi3"; else if (p->n_op == MUL && p->n_type == INT) ch = "mulsi3"; @@ -450,7 +687,67 @@ emul(NODE *p) else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negdi2"; else ch = 0, comperr("ZE"); - printf("\tbl __%s\t@ emulated operation\n", exname(ch)); + printf("\tbl __%s" COM "emulated operation\n", exname(ch)); +} + +static void +halfword(NODE *p) +{ + NODE *r = getlr(p, 'R'); + NODE *l = getlr(p, 'L'); + int idx0 = 0, idx1 = 1; + + if (features(FEATURE_BIGENDIAN)) { + idx0 = 1; + idx1 = 0; + } + + if (p->n_op == ASSIGN && r->n_op == OREG) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx0); + expand(p, 0, "\tldrb AL,"); + printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx1); + expand(p, 0, "\torr AL,A1,AL,asl #8\n"); + } else if (p->n_op == ASSIGN && l->n_op == OREG) { + /* store */ + expand(p, 0, "\tstrb AR,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0); + expand(p, 0, "\tmov A1,AR,asr #8\n"); + expand(p, 0, "\tstrb A1,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1); + } else if (p->n_op == SCONV || p->n_op == UMUL) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0); + expand(p, 0, "\tldrb A2,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1); + expand(p, 0, "\torr A1,A1,A2,asl #8\n"); + } else if (p->n_op == NAME || p->n_op == ICON || p->n_op == OREG) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx0); + expand(p, 0, "\tldrb A2,"); + printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx1); + expand(p, 0, "\torr A1,A1,A2,asl #8\n"); + } else { + comperr("halfword"); + } +} + +static void +bfext(NODE *p) +{ + int sz; + + if (ISUNSIGNED(p->n_right->n_type)) + return; + sz = 32 - UPKFSZ(p->n_left->n_rval); + + expand(p, 0, "\tmov AD,AD,asl "); + printf("#%d\n", sz); + expand(p, 0, "\tmov AD,AD,asr "); + printf("#%d\n", sz); } static int @@ -460,10 +757,10 @@ argsiz(NODE *p) if (t < LONGLONG || t == FLOAT || t > BTMASK) return 4; - if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) + if (t == LONGLONG || t == ULONGLONG) + return 8; + if (t == DOUBLE || t == LDOUBLE) return 8; - if (t == LDOUBLE) - return 12; if (t == STRTY || t == UNIONTY) return p->n_stsize; comperr("argsiz"); @@ -477,11 +774,9 @@ zzzcode(NODE *p, int c) switch (c) { -#if 0 - case 'B': /* Assign to bitfield */ - bfasg(p); + case 'B': /* bit-field sign extension */ + bfext(p); break; -#endif case 'C': /* remove from stack after subroutine call */ pr = p->n_qual; @@ -507,18 +802,22 @@ zzzcode(NODE *p, int c) fpemul(p); break; - case 'I': /* init constant */ - if (p->n_name[0] != '\0') - comperr("named init"); - fprintf(stdout, "=%lld", p->n_lval & 0xffffffff); - break; + case 'H': /* do halfword access */ + halfword(p); + break; + + case 'I': /* init constant */ + if (p->n_name[0] != '\0') + comperr("named init"); + load_constant_into_reg(DECRA(p->n_reg, 1), + p->n_lval & 0xffffffff); + break; case 'J': /* init longlong constant */ - expand(p, INBREG, "\tldr A1,"); - fprintf(stdout, "=%lld\t@ load 64-bit constant\n", + load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1, p->n_lval & 0xffffffff); - expand(p, INBREG, "\tldr U1,"); - fprintf(stdout, "=%lld\n", (p->n_lval >> 32)); + load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1 + 1, + (p->n_lval >> 32)); break; case 'O': /* 64-bit left and right shift operators */ @@ -610,11 +909,16 @@ conput(FILE *fp, NODE *p) if (p->n_sp) printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel); #endif +#ifdef notdef /* ICON cannot ever use sp here */ + /* If it does, it's a giant bug */ if (p->n_sp == NULL || (p->n_sp->sclass == ILABEL || (p->n_sp->sclass == STATIC && p->n_sp->slevel > 0))) s = p->n_name; else s = exname(p->n_name); +#else + s = p->n_name; +#endif if (*s != '\0') { fprintf(fp, "%s", s); @@ -688,7 +992,13 @@ adrput(FILE *io, NODE *p) case OREG: r = p->n_rval; - fprintf(io, "[%s,#%d]", rnames[p->n_rval], (int)p->n_lval); + if (R2TEST(r)) + fprintf(io, "[%s, %s, lsl #%d]", + rnames[R2UPK1(r)], + rnames[R2UPK2(r)], + R2UPK3(r)); + else + fprintf(io, "[%s,#%d]", rnames[p->n_rval], (int)p->n_lval); return; case ICON: @@ -696,13 +1006,15 @@ adrput(FILE *io, NODE *p) conput(io, p); return; - case MOVE: case REG: switch (p->n_type) { -#if !defined(ARM_HAS_FPA) && !defined(ARM_HAS_VFP) case DOUBLE: case LDOUBLE: -#endif + if (features(FEATURE_HARDFLOAT)) { + fprintf(io, "%s", rnames[p->n_rval]); + break; + } + /* FALLTHROUGH */ case LONGLONG: case ULONGLONG: fprintf(stdout, "%s", rnames[p->n_rval-R0R1]); @@ -725,16 +1037,73 @@ cbgen(int o, int lab) { if (o < EQ || o > UGT) comperr("bad conditional branch: %s", opst[o]); - printf("\t%s " LABFMT "\t@ conditional branch\n", + printf("\t%s " LABFMT COM "conditional branch\n", ccbranches[o-EQ], lab); } +/* + * The arm can only address 4k to get a NAME, so there must be some + * rewriting here. Strategy: + * For first 1000 nodes found, print out the word directly. + * For the following 1000 nodes, group them together in asm statements + * and create a jump over. + * For the last <1000 statements, print out the words last. + */ struct addrsymb { - DLIST_ENTRY(addrsymb) link; - struct symtab *orig; - struct symtab *new; + SLIST_ENTRY(addrsymb) link; + char *name; /* symbol name */ + int num; /* symbol offset */ + char *str; /* replace label */ }; -struct addrsymb addrsymblist; +SLIST_HEAD(, addrsymb) aslist; +static struct interpass *ipbase; +static int prtnumber, nodcnt, notfirst; +#define PRTLAB ".LY%d" /* special for here */ + +static struct interpass * +anode(char *p) +{ + extern int thisline; + struct interpass *ip = tmpalloc(sizeof(struct interpass)); + + ip->ip_asm = p; + ip->type = IP_ASM; + ip->lineno = thisline; + return ip; +} + +static void +flshlab(void) +{ + struct interpass *ip; + struct addrsymb *el; + int lab = prtnumber++; + char *c; + + if (SLIST_FIRST(&aslist) == NULL) + return; + + snprintf(c = tmpalloc(32), 32, "\tb " PRTLAB "\n", lab); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); + + SLIST_FOREACH(el, &aslist, link) { + /* insert each node as asm */ + int l = 32+strlen(el->name); + c = tmpalloc(l); + if (el->num) + snprintf(c, l, "%s:\n\t.word %s+%d\n", + el->str, el->name, el->num); + else + snprintf(c, l, "%s:\n\t.word %s\n", el->str, el->name); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); + } + /* generate asm label */ + snprintf(c = tmpalloc(32), 32, PRTLAB ":\n", lab); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); +} static void prtaddr(NODE *p) @@ -744,39 +1113,65 @@ prtaddr(NODE *p) int found = 0; int lab; + nodcnt++; + + if (p->n_op == ASSIGN && p->n_right->n_op == ICON && + p->n_right->n_name[0] != '\0') { + /* named constant */ + p = p->n_right; + + /* Restore addrof */ + l = mklnode(NAME, p->n_lval, 0, 0); + l->n_name = p->n_name; + p->n_left = l; + p->n_op = ADDROF; + } + if (p->n_op != ADDROF || l->n_op != NAME) return; + /* if we passed 1k nodes printout list */ + if (nodcnt > 1000) { + if (notfirst) + flshlab(); + SLIST_INIT(&aslist); + notfirst = 1; + nodcnt = 0; + } + /* write address to byte stream */ - DLIST_FOREACH(el, &addrsymblist, link) { - if (el->orig == l->n_sp) { + SLIST_FOREACH(el, &aslist, link) { + if (el->num == l->n_lval && el->name[0] == l->n_name[0] && + strcmp(el->name, l->n_name) == 0) { found = 1; break; } } if (!found) { - setloc1(PROG); - defalign(SZPOINT(l->n_type)); - deflab1(lab = getlab()); - printf("\t.word "); - adrput(stdout, l); - printf("\n"); + /* we know that this is text segment */ + lab = prtnumber++; + if (nodcnt <= 1000 && notfirst == 0) { + if (l->n_lval) + printf(PRTLAB ":\n\t.word %s+%lld\n", + lab, l->n_name, l->n_lval); + else + printf(PRTLAB ":\n\t.word %s\n", + lab, l->n_name); + } el = tmpalloc(sizeof(struct addrsymb)); - el->orig = l->n_sp; - el->new = tmpalloc(sizeof(struct symtab_hdr)); - el->new->sclass = ILABEL; - el->new->soffset = lab; - el->new->sflags = 0; - DLIST_INSERT_BEFORE(&addrsymblist, el, link); + el->num = l->n_lval; + el->name = l->n_name; + el->str = tmpalloc(32); + snprintf(el->str, 32, PRTLAB, lab); + SLIST_INSERT_LAST(&aslist, el, link); } nfree(l); p->n_op = NAME; p->n_lval = 0; - p->n_sp = el->new; - p2tree(p); + p->n_name = el->str; } void @@ -784,12 +1179,24 @@ myreader(struct interpass *ipole) { struct interpass *ip; - DLIST_INIT(&addrsymblist, link); + SLIST_INIT(&aslist); + notfirst = nodcnt = 0; DLIST_FOREACH(ip, ipole, qelem) { - if (ip->type != IP_NODE) - continue; - walkf(ip->ip_node, prtaddr); + switch (ip->type) { + case IP_NODE: + lineno = ip->lineno; + ipbase = ip; + walkf(ip->ip_node, prtaddr); + break; + case IP_EPILOG: + ipbase = ip; + if (notfirst) + flshlab(); + break; + default: + break; + } } if (x2debug) printip(ipole); @@ -839,30 +1246,41 @@ void rmove(int s, int d, TWORD t) { switch (t) { -#if !defined(ARM_HAS_FPU) && !defined(ARM_HAS_VFP) case DOUBLE: case LDOUBLE: -#endif + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALLTHROUGH */ case LONGLONG: case ULONGLONG: #define LONGREG(x, y) rnames[(x)-(R0R1-(y))] if (s == d+1) { /* dh = sl, copy low word first */ - printf("\tmov %s,%s @ rmove\n", + printf("\tmov %s,%s" COM "rmove\n", LONGREG(d,0), LONGREG(s,0)); printf("\tmov %s,%s\n", LONGREG(d,1), LONGREG(s,1)); } else { /* copy high word first */ - printf("\tmov %s,%s @ rmove\n", + printf("\tmov %s,%s" COM "rmove\n", LONGREG(d,1), LONGREG(s,1)); printf("\tmov %s,%s\n", LONGREG(d,0), LONGREG(s,0)); } #undef LONGREG break; + case FLOAT: + if (features(FEATURE_HARDFLOAT)) { + printf("\tmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALLTHROUGH */ default: - printf("\tmov %s,%s @ rmove\n", rnames[d], rnames[s]); + printf("\tmov %s,%s" COM "rmove\n", rnames[d], rnames[s]); } } @@ -911,9 +1329,14 @@ COLORMAP(int c, int *r) return num < 6; /* XXX see comments above */ case CLASSC: num += r[CLASSC]; - return num < 8; + if (features(FEATURE_FPA)) + return num < 8; + else if (features(FEATURE_VFP)) + return num < 8; + else + cerror("colormap 1"); } - assert(0); + cerror("colormap 2"); return 0; /* XXX gcc */ } @@ -923,15 +1346,34 @@ COLORMAP(int c, int *r) int gclass(TWORD t) { -#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP) - if (t == FLOAT || t == DOUBLE || t == LDOUBLE) - return CLASSC; -#endif - if (t == DOUBLE || t == LDOUBLE || t == LONGLONG || t == ULONGLONG) + if (t == DOUBLE || t == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + else + return CLASSB; + } + if (t == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + else + return CLASSA; + } + if (DEUNSIGN(t) == LONGLONG) return CLASSB; return CLASSA; } +int +retreg(int t) +{ + int c = gclass(t); + if (c == CLASSB) + return R0R1; + else if (c == CLASSC) + return F0; + return R0; +} + /* * Calculate argument sizes. */ @@ -960,9 +1402,129 @@ special(NODE *p, int shape) } /* + * default to ARMv2 + */ +#ifdef TARGET_BIG_ENDIAN +#define DEFAULT_FEATURES FEATURE_BIGENDIAN | FEATURE_MUL +#else +#define DEFAULT_FEATURES FEATURE_MUL +#endif + +static int fset = DEFAULT_FEATURES; + +/* * Target-dependent command-line options. */ void mflags(char *str) { + if (strcasecmp(str, "little-endian") == 0) { + fset &= ~FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "big-endian") == 0) { + fset |= FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "fpe=fpa") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + fset |= FEATURE_FPA; + } else if (strcasecmp(str, "fpe=vfp") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + fset |= FEATURE_VFP; + } else if (strcasecmp(str, "soft-float") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + } else if (strcasecmp(str, "arch=armv1") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset &= ~FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv2") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv2a") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv3") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4t") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4tej") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5te") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5tej") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6t2") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6kz") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6k") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv7") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else { + fprintf(stderr, "unknown m option '%s'\n", str); + exit(1); + } } + +int +features(int mask) +{ + if (mask == FEATURE_HARDFLOAT) + return ((fset & mask) != 0); + return ((fset & mask) == mask); +} + +/* + * Define the current location as an internal label. + */ +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + diff --git a/usr.bin/pcc/arm/macdefs.h b/usr.bin/pcc/arm/macdefs.h index df8db2007db..a9564fd1082 100644 --- a/usr.bin/pcc/arm/macdefs.h +++ b/usr.bin/pcc/arm/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.2 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: macdefs.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -145,8 +145,17 @@ typedef long long OFFSZ; #define R8R9 24 #define R9R10 25 -#define NUMCLASS 2 -#define MAXREGS 26 +#define F0 26 +#define F1 27 +#define F2 28 +#define F3 29 +#define F4 30 +#define F5 31 +#define F6 32 +#define F7 33 + +#define NUMCLASS 3 +#define MAXREGS 34 #define RSTATUS \ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ @@ -155,6 +164,8 @@ typedef long long OFFSZ; 0, 0, 0, 0, 0, \ SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG, \ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, \ #define ROVERLAP \ { R0R1, -1 }, \ @@ -183,6 +194,14 @@ typedef long long OFFSZ; { R7, R8, R6R7, R8R9, -1 }, \ { R8, R9, R7R8, R9R10, -1 }, \ { R9, R10, R8R9, -1 }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ #define BACKTEMP /* stack grows negatively for temporaries */ #define BACKAUTO /* stack grows negatively for automatics */ @@ -190,35 +209,42 @@ typedef long long OFFSZ; #define ARGINIT (4*8) /* # bits above fp where arguments start */ #define AUTOINIT (12*8) /* # bits above fp where automatics start */ +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES 1 /* bytes are numbered right to left */ + /* XXX - to die */ #define FPREG FP /* frame pointer */ /* Return a register class based on the type of the node */ #define PCLASS(p) (1 << gclass((p)->n_type)) -#define GCLASS(x) (x < 16 ? CLASSA : CLASSB) +#define GCLASS(x) (x < 16 ? CLASSA : x < 26 ? CLASSB : CLASSC) #define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ #define ENCRD(x) (x) /* Encode dest reg in n_reg */ #define ENCRA1(x) ((x) << 6) /* A1 */ #define ENCRA2(x) ((x) << 12) /* A2 */ #define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ - -#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP) -#define RETREG(x) (DEUNSIGN(x) == LONGLONG ? R0R1 : \ - (x) == DOUBLE || (x) == LDOUBLE || (x) == FLOAT ? \ - F0 : R0) -#else -#define RETREG(x) (DEUNSIGN(x) == LONGLONG || \ - (x) == DOUBLE || (x) == LDOUBLE ? R0R1 : R0) -#endif +#define RETREG(x) retreg(x) int COLORMAP(int c, int *r); +int retreg(int ty); +int features(int f); + +#define FEATURE_BIGENDIAN 0x00010000 +#define FEATURE_HALFWORDS 0x00020000 /* ldrsh/ldrh, ldrsb */ +#define FEATURE_EXTEND 0x00040000 /* sxth, sxtb, uxth, uxtb */ +#define FEATURE_MUL 0x00080000 +#define FEATURE_MULL 0x00100000 +#define FEATURE_FPA 0x10000000 +#define FEATURE_VFP 0x20000000 +#define FEATURE_HARDFLOAT (FEATURE_FPA|FEATURE_VFP) -#define TARGET_STDARGS \ - { "__builtin_stdarg_start, arm_builtin_stdarg_start }, \ - { "__builtin_va_arg, arm_builtin_va_arg }, \ - { "__builtin_va_end, arm_builtin_va_end }, \ - { "__builtin_va_copy, arm_builtin_va_copy }, +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", arm_builtin_stdarg_start }, \ + { "__builtin_va_arg", arm_builtin_va_arg }, \ + { "__builtin_va_end", arm_builtin_va_end }, \ + { "__builtin_va_copy", arm_builtin_va_copy }, #define NODE struct node struct node; @@ -227,3 +253,6 @@ NODE *arm_builtin_va_arg(NODE *f, NODE *a); NODE *arm_builtin_va_end(NODE *f, NODE *a); NODE *arm_builtin_va_copy(NODE *f, NODE *a); #undef NODE + +#define COM "\t@ " +#define NARGREGS 4 diff --git a/usr.bin/pcc/arm/order.c b/usr.bin/pcc/arm/order.c index 16798daec77..7b60b357cb6 100644 --- a/usr.bin/pcc/arm/order.c +++ b/usr.bin/pcc/arm/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.2 2007/12/22 12:38:56 stefan Exp $ */ +/* $OpenBSD: order.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -81,11 +81,27 @@ offstar(NODE *p, int shape) } /* - * It is OK to do an OREG - Modify the expression tree to be an OREG. + * Unable to convert to OREG (notoff() returned failure). Output + * suitable instructions to replace OREG. */ void myormake(NODE *q) { + NODE *p, *r; + + if (x2debug) + printf("myormake(%p)\n", q); + + p = q->n_left; + if (p->n_op == PLUS && (r = p->n_right)->n_op == LS && + r->n_right->n_op == ICON && r->n_right->n_lval == 2 && + p->n_left->n_op == REG && r->n_left->n_op == REG) { + q->n_op = OREG; + q->n_lval = 0; + q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, + r->n_right->n_lval); + tfree(p); + } } /* @@ -298,5 +314,5 @@ livecall(NODE *p) int acceptable(struct optab *op) { - return 1; + return features(op->visit & 0xffff0000); } diff --git a/usr.bin/pcc/arm/table.c b/usr.bin/pcc/arm/table.c index fcf715dbc09..89f6e707c35 100644 --- a/usr.bin/pcc/arm/table.c +++ b/usr.bin/pcc/arm/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.1 2007/11/25 18:45:06 otto Exp $ */ +/* $OpenBSD: table.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /*- * Copyright (c) 2007 Gregory McGarry <g.mcgarry@ieee.org> * @@ -32,32 +32,6 @@ #define TSWORD TINT|TLONG #define TWORD TUWORD|TSWORD -#if defined(ARM_HAS_FPA) || defined(ARM_HAS_VFP) -#define INFREG INCREG -#define NFREG NCREG -#define SFREG SCREG -#define NFSL NCSL -#define NFSR NCSR -#define INXREG INCREG -#define NXREG NCREG -#define SXREG SCREG -#define NXSL NCSL -#define NXSR NCSR -#else -#define INFREG INAREG -#define NFREG NAREG -#define SFREG SAREG -#define NFSL NASL -#define NFSR NASR -#define INXREG INBREG -#define NXREG NBREG -#define SXREG SBREG -#define NXSL NBSL -#define NXSR NBSR -#endif - -#define COM " @ " - struct optab table[] = { /* First entry must be an empty entry */ { -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, @@ -69,6 +43,7 @@ struct optab table[] = { 0, RLEFT, COM "pointer conversion\n", }, + /* * Conversions of integral types * @@ -86,92 +61,140 @@ struct optab table[] = { */ { SCONV, INAREG, - INAREG, TCHAR, - INAREG, TSWORD|TSHORT, - NAREG|NASL, RESC1, + SAREG, TCHAR, + SAREG, TSWORD|TSHORT, + 0, RLEFT, COM "convert char to short/int\n", }, { SCONV, INAREG, - INAREG, TCHAR, - INAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, NAREG|NASL, RESC1, " and A1,AL,#255" COM "convert char to uchar/ushort/uint\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TUCHAR, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert uchar to char\n", }, + { SCONV, INAREG, - INAREG, TUCHAR, - INAREG, TCHAR, + SAREG, TUCHAR, + SAREG, TCHAR, NAREG|NASL, RESC1, " mov A1,AL,asl #24" COM "convert uchar to char\n" " mov A1,A1,asr #24\n", }, { SCONV, INAREG, - INAREG, TUCHAR, - INAREG, TWORD|TSHORT|TUSHORT, + SAREG, TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT, 0, RLEFT, COM "convert uchar to (u)short/(u)int\n", }, { SCONV, INAREG, - INAREG, TSHORT, - INAREG, TSWORD, + SAREG, TSHORT, + SAREG, TSWORD, 0, RLEFT, COM "convert short to int\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TSHORT, + SAREG, TUWORD, + NAREG|NASL, RESC1, + " uxth A1,AL" COM "convert short to uint\n", }, + { SCONV, INAREG, - INAREG, TSHORT, - INAREG, TUWORD, + SAREG, TSHORT, + SAREG, TUWORD, NAREG|NASL, RESC1, " mov A1,AL,asl #16" COM "convert short to uint\n" " mov A1,AL,lsr #16\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TUSHORT, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sxth A1,AL" COM "convert ushort to short\n", }, + { SCONV, INAREG, - INAREG, TUSHORT, - INAREG, TSHORT, + SAREG, TUSHORT, + SAREG, TSHORT, NAREG|NASL, RESC1, " mov A1,AL,asl #16" COM "convert ushort to short\n" " mov A1,A1,asr #16\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert (u)short to char\n", }, + { SCONV, INAREG, - INAREG, TSHORT|TUSHORT, - INAREG, TCHAR, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, NAREG|NASL, RESC1, " mov A1,AL,asl #24" COM "convert (u)short to char\n" " mov A1,A1,asr #24\n", }, { SCONV, INAREG, - INAREG, TSHORT|TUSHORT, - INAREG, TUCHAR, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, NAREG|NASL, RESC1, - " and A1,AL,#255" COM "convert (u)short to uchar\n", }, + " sxtb A1,AL" COM "convert (u)short to char\n", }, { SCONV, INAREG, - INAREG, TUSHORT, - INAREG, TWORD, + SAREG, TSHORT|TUSHORT, + SAREG, TUCHAR, NAREG|NASL, RESC1, + " and A1,AL,#255" COM "convert (u)short to uchar\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TWORD, + 0, RLEFT, COM "convert ushort to (u)int\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert (u)int to char\n", }, + { SCONV, INAREG, - INAREG, TWORD, - INAREG, TCHAR, + SAREG, TWORD, + SAREG, TCHAR, NAREG|NASL, RESC1, " mov A1,AL,asl #24" COM "convert (u)int to char\n" " mov A1,A1,asr #24\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sxth A1,AL" COM "convert (u)int to short\n", }, + { SCONV, INAREG, - INAREG, TWORD, - INAREG, TSHORT, + SAREG, TWORD, + SAREG, TSHORT, NAREG|NASL, RESC1, " mov A1,AL,asl #16" COM "convert (u)int to short\n" " mov A1,A1,asr #16\n", }, { SCONV, INAREG, - INAREG, TWORD, - INAREG, TUCHAR, + SAREG, TWORD, + SAREG, TUCHAR, NAREG|NASL, RESC1, " and A1,AL,#255" COM "convert uchar to char\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " uxth A1,AL" COM "convert int to ushort\n", }, + { SCONV, INAREG, - INAREG, TWORD, - INAREG, TUSHORT, + SAREG, TWORD, + SAREG, TUSHORT, NAREG|NASL, RESC1, " mov A1,AL,asl #16" COM "convert int to ushort\n" " mov A1,AL,lsr #16\n", }, @@ -196,6 +219,12 @@ struct optab table[] = { " mov A1,AL" COM "convert (u)char/(u)short/(u)int to (u)longlong\n" " mov U1,AL,asr #31\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR, + NAREG, RESC1, + " sxtb A1,AL" COM "convert (u)longlong to char\n", }, + { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TCHAR, @@ -203,6 +232,12 @@ struct optab table[] = { " mov A1,AL,asl #24" COM "convert (u)longlong to char\n" " mov A1,A1,asr #24\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT, + NAREG, RESC1, + " sxth A1,AL" COM "convert (u)longlong to short\n", }, + { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TSHORT, @@ -222,6 +257,12 @@ struct optab table[] = { NAREG, RESC1, " and A1,AL,#255" COM "convert (u)longlong to uchar\n", }, +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUSHORT, + NAREG, RESC1, + " uxth A1,AL" COM "convert (u)longlong to ushort\n", }, + { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TUSHORT, @@ -246,287 +287,287 @@ struct optab table[] = { " ldrb A1,AL" COM "convert uchar to int/long\n", }, /* short */ -{ SCONV, INAREG, +{ SCONV, INAREG | FEATURE_HALFWORDS, SOREG, TSHORT, SAREG, TWORD, NASL|NAREG, RESC1, " ldrsh A1,AL" COM "convert short to int/long\n", }, /* ushort */ -{ SCONV, INAREG, +{ SCONV, INAREG | FEATURE_HALFWORDS, SOREG, TSHORT, SAREG, TWORD, NASL|NAREG, RESC1, " ldrh A1,AL" COM "convert ushort to int/long\n", }, +/* short */ { SCONV, INAREG, - SFREG, TFLOAT, - SAREG, TSWORD, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA + SOREG, TSHORT|TUSHORT, + SAREG, TWORD, + 2*NAREG|NASL, RESC1, + "ZH", }, + +{ SCONV, INAREG | FEATURE_FPA, + SCREG, TFLOAT, + SAREG, TWORD, + NAREG, RESC1, " fix AL,AR" COM "convert float to int\n", }, -#elifdef ARM_HAS_VFP + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TFLOAT, + SAREG, TSWORD, + NAREG, RESC1, " ftosis AL,AR" COM "convert float to int\n", }, -#else - "ZF", }, -#endif -{ SCONV, INAREG, - SFREG, TFLOAT, - SAREG, TUWORD, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA - " fix AL,AR" COM "convert float to int\n", }, -#elifdef ARM_HAS_VFP +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TFLOAT, + SAREG, TSWORD, + NAREG, RESC1, " ftouis AL,AR" COM "convert float to int\n", }, -#else - "ZF", }, -#endif -{ SCONV, INBREG, - SFREG, TFLOAT, - SBREG, TULONGLONG, +{ SCONV, INAREG, + SAREG, TFLOAT, + SAREG, TWORD, NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else "ZF", }, -#endif + +{ SCONV, INBREG | FEATURE_FPA, + SCREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG | FEATURE_VFP, + SCREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, { SCONV, INBREG, - SFREG, TFLOAT, - SBREG, TLONGLONG, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else + SAREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INAREG, - SXREG, TDOUBLE|TLDOUBLE, - SAREG, TSWORD, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA +{ SCONV, INAREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NAREG, RESC1, " fix AL,AR" COM "convert double/ldouble to int\n", }, -#elifdef ARM_HAS_VFP + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TSWORD, + NAREG, RESC1, " ftosid AL,AR" COM "convert double/ldouble to int\n", }, -#else - "ZF", }, -#endif -{ SCONV, INAREG, - SXREG, TDOUBLE|TLDOUBLE, +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, SAREG, TUWORD, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA - " fix AL,AR" COM "convert double/ldouble to int\n", }, -#elifdef ARM_HAS_VFP + NAREG, RESC1, " ftouid AL,AR" COM "convert double/ldouble to int\n", }, -#else - "ZF", }, -#endif -{ SCONV, INBREG, - SXREG, TDOUBLE|TLDOUBLE, - SBREG, TULONGLONG, +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else "ZF", }, -#endif + +{ SCONV, INBREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, { SCONV, INBREG, - SXREG, TDOUBLE|TLDOUBLE, - SBREG, TLONGLONG, - NSPECIAL|NAREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TULONGLONG|TLONGLONG, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INFREG, - SAREG, TSWORD, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TFLOAT, + NCREG, RESC1, " flts AL,AR" COM "convert int to float\n" }, -#elifdef ARM_HAS_VFP + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TFLOAT, + NCREG, RESC1, " fsitos AL,AR" COM "convert int to float\n" }, -#else - "ZF", }, -#endif -{ SCONV, INFREG, +{ SCONV, INCREG | FEATURE_VFP, SAREG, TUWORD, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA - " flts AL,AR" COM "convert int to float\n" }, -#elifdef ARM_HAS_VFP + SCREG, TFLOAT, + NCREG, RESC1, " fuitos AL,AR" COM "convert int to float\n" }, -#else - "ZF", }, -#endif -{ SCONV, INFREG, - SBREG, TLONGLONG, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ SCONV, INFREG, - SBREG, TULONGLONG, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else - "ZF", }, -#endif +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TULONGLONG|TLONGLONG, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, -{ SCONV, INXREG, - SAREG, TSWORD, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TULONGLONG|TLONGLONG, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INAREG, + SBREG, TULONGLONG|TLONGLONG, + SAREG, TFLOAT, + NAREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TDOUBLE, + NCREG, RESC1, " fltd AL,AR" COM "convert int to double\n" }, -#elifdef ARM_HAS_VFP + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TDOUBLE, + NCREG, RESC1, " fsitod AL,AR" COM "convert int to double\n" }, -#else - "ZF", }, -#endif -{ SCONV, INXREG, +{ SCONV, INCREG | FEATURE_VFP, SAREG, TUWORD, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA - " fltd AL,AR" COM "convert int to double\n" }, -#elifdef ARM_HAS_VFP + SCREG, TDOUBLE, + NCREG, RESC1, " fuitod AL,AR" COM "convert int to double\n" }, -#else - "ZF", }, -#endif -{ SCONV, INXREG, - SBREG, TLONGLONG, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INXREG, - SBREG, TULONGLONG, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INXREG, - SAREG, TSWORD, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, " flte AL,AR" COM "convert int to ldouble\n" }, -#elifdef ARM_HAS_VFP + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, " fsitod AL,AR" COM "convert int to ldouble\n" }, -#else - "ZF", }, -#endif -{ SCONV, INXREG, +{ SCONV, INCREG | FEATURE_VFP, SAREG, TUWORD, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA - " flte AL,AR" COM "convert int to ldouble\n" }, -#elifdef ARM_HAS_VFP - " fuitod AL,AR" COM "convert int to ldouble\n" }, -#else + SCREG, TLDOUBLE, + NCREG, RESC1, + " fuitod AL,AR" COM "convert uint to ldouble\n" }, + +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, -{ SCONV, INXREG, - SBREG, TLONGLONG, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else - "ZF", }, -#endif +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, -{ SCONV, INXREG, - SBREG, TULONGLONG, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP -#else +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INFREG, - SXREG, TDOUBLE, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP - " fcvtds AL,AR" COM "convert float to double\n" }, -#else - "ZF", }, -#endif +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, -{ SCONV, INFREG, - SXREG, TLDOUBLE, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, " fcvtds AL,AR" COM "convert float to double\n" }, -#else - "ZF", }, -#endif -{ SCONV, INXREG, - SFREG, TFLOAT, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP - " fcvtsd AL,AR" COM "convert float to double\n" }, -#else +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ SCONV, INXREG, - SFREG, TFLOAT, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA -#elifdef ARM_HAS_VFP +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, " fcvtsd AL,AR" COM "convert float to double\n" }, -#else + +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ SCONV, INXREG, - SXREG, TDOUBLE|TLDOUBLE, - SXREG, TDOUBLE|TLDOUBLE, +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double", }, + +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double", }, + +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, 0, RLEFT, COM "convert (l)double to (l)double", }, @@ -561,17 +602,31 @@ struct optab table[] = { " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" "ZC", }, -{ CALL, INFREG, +{ CALL, INCREG | FEATURE_FPA, SCON|SNAME, TANY, - SFREG, TFLOAT, - NFREG|NASL, RESC1, /* should be 0 */ + SCREG, TFLOAT, + NCREG|NCSL, RESC1, /* should be 0 */ " bl CL" COM "call (args, result r0) to scon/sname (CL)\n" "ZC", }, -{ CALL, INXREG, +{ CALL, INCREG | FEATURE_FPA, + SCON|SNAME, TANY, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INAREG, SCON|SNAME, TANY, - SXREG, TDOUBLE|TLDOUBLE, - NXREG|NXSL, RESC1, /* should be 0 */ + SAREG, TFLOAT, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result r0) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INBREG, + SCON|SNAME, TANY, + SBREG, TDOUBLE|TLDOUBLE, + NBREG|NBSL, RESC1, /* should be 0 */ " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" "ZC", }, @@ -587,16 +642,16 @@ struct optab table[] = { NBREG|NBSL, RESC1, /* should be 0 */ " bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", }, -{ UCALL, INFREG, +{ UCALL, INCREG | FEATURE_FPA, SCON|SNAME, TANY, - SFREG, TFLOAT, - NFREG|NFSL, RESC1, /* should be 0 */ + SCREG, TFLOAT, + NCREG|NCSL, RESC1, /* should be 0 */ " bl CL" COM "call (no args, result in r0) to scon/sname (CL)\n", }, -{ UCALL, INXREG, +{ UCALL, INCREG | FEATURE_FPA, SCON|SNAME, TANY, - SXREG, TDOUBLE|TLDOUBLE, - NXREG|NXSL, RESC1, /* should be 0 */ + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ " bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", }, { CALL, FOREFF, @@ -614,11 +669,26 @@ struct optab table[] = { " mov lr,pc\n" " mov pc,AL\n", }, +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + INAREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n" + "ZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + INAREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n", }, + /* struct return */ { USTCALL, FOREFF, SCON, TANY, SANY, TANY, - NAREG|NASL, 0, + 0, 0, " bl CL\n", }, { USTCALL, INAREG, @@ -637,7 +707,7 @@ struct optab table[] = { { STCALL, FOREFF, SCON, TANY, SANY, TANY, - NAREG|NASL, 0, + 0, 0, " bl CL\n" "ZC", }, @@ -686,41 +756,59 @@ struct optab table[] = { " adds A1,AL,AR" COM "64-bit addition\n" " adc U1,UL,UR\n", }, -{ PLUS, INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " adfs A1,AL,AR" COM "float add\n", }, -#elifdef ARM_HAS_VFP + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " fadds A1,AL,AR" COM "float add\n", }, -#else + +{ PLUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ PLUS, INXREG, - SXREG, TDOUBLE, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " adfd A1,AL,AR" COM "double add\n", }, -#elifdef ARM_HAS_VFP + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " faddd A1,AL,AR" COM "double add\n", }, -#else + +{ PLUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ PLUS, INXREG, - SXREG, TLDOUBLE, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " adfe A1,AL,AR" COM "ldouble add\n", }, -#elifdef ARM_HAS_VFP + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " faddd A1,AL,AR" COM "ldouble add\n", }, -#else + +{ PLUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif { MINUS, INAREG, SAREG, TWORD|TPOINT, @@ -732,7 +820,7 @@ struct optab table[] = { SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NASL, RESC1, - " sub A1,AR,AL" COM "subtraction\n", }, + " sub A1,AL,AR" COM "subtraction\n", }, { MINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, @@ -748,41 +836,59 @@ struct optab table[] = { " subs A1,AL,AR" COM "64-bit subtraction\n" " sbc U1,UL,AR\n", }, -{ MINUS, INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " sufs A1,AL,AR" COM "float subtraction\n", }, -#elifdef ARM_HAS_VFP + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " fsubs A1,AL,AR" COM "float subtraction\n", }, -#else + +{ MINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ MINUS, INXREG, - SXREG, TDOUBLE, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " sufd A1,AL,AR" COM "double subtraction\n", }, -#elifdef ARM_HAS_VFP + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " fsubd A1,AL,AR" COM "double subtraction\n", }, -#else + +{ MINUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ MINUS, INXREG, - SXREG, TLDOUBLE, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " sufe A1,AL,AR" COM "ldouble subtraction\n", }, -#elifdef ARM_HAS_VFP + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " fsubd A1,AL,AR" COM "double subtraction\n", }, -#else + +{ MINUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif /* * The next rules handle all shift operators. @@ -790,7 +896,7 @@ struct optab table[] = { { LS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TANY, NAREG|NASL, RESC1, " mov A1,AL,asl AR" COM "left shift\n", }, @@ -806,15 +912,21 @@ struct optab table[] = { NBREG, RESC1, "ZO" }, +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE" }, + { RS, INAREG, SAREG, TSWORD|TSHORT|TCHAR, - SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TANY, NAREG|NASL, RESC1, " mov A1,AL,asr AR" COM "right shift\n", }, { RS, INAREG, SAREG, TUWORD|TUSHORT|TUCHAR, - SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TANY, NAREG|NASL, RESC1, " mov A1,AL,lsr AR" COM "right shift\n", }, @@ -836,6 +948,13 @@ struct optab table[] = { NBREG, RESC1, "ZO" }, +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE" }, + + /* * The next rules takes care of assignments. "=". */ @@ -866,46 +985,73 @@ struct optab table[] = { 0, RDEST, " strb AR,AL" COM "assign (u)char\n", }, -{ ASSIGN, FOREFF|INAREG, +{ ASSIGN, FOREFF|INAREG | FEATURE_HALFWORDS, SOREG|SNAME, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, 0, RDEST, " strh AR,AL" COM "assign (u)short\n", }, -{ ASSIGN, FOREFF|INFREG, +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RDEST, + "ZH", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, SOREG|SNAME, TFLOAT, - SFREG, TFLOAT, + SCREG, TFLOAT, 0, RDEST, -#ifdef ARM_HAS_FPA " stfs AR,AL" COM "assign float\n", }, -#elifdef ARM_HAS_VFP -#else - " str AR,AL" COM "assign float\n", }, -#endif -{ ASSIGN, FOREFF|INXREG, +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + COM "unimplemented\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " str AR,AL" COM "assign float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, SOREG|SNAME, TDOUBLE, - SXREG, TDOUBLE, + SCREG, TDOUBLE, 0, RDEST, -#ifdef ARM_HAS_FPA " stfd AR,AL" COM "assign double\n", }, -#elifdef ARM_HAS_VFP -#else - " str AR,AL" COM "assign double\n" + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + COM "unimplemented\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TDOUBLE, + SBREG, TDOUBLE, + 0, RDEST, + " str AR,AL" COM "assign double (soft-float)\n" " str UR,UL\n", }, -#endif -{ ASSIGN, FOREFF|INXREG, +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, SOREG|SNAME, TLDOUBLE, - SXREG, TLDOUBLE, + SCREG, TLDOUBLE, 0, RDEST, -#ifdef ARM_HAS_FPA " stfe AR,AL" COM "assign ldouble\n", }, -#elifdef ARM_HAS_VFP -#else - " str AR,AL" COM "assign ldouble\n" + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RDEST, + COM "not implemented", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TLDOUBLE, + SBREG, TLDOUBLE, + 0, RDEST, + " str AR,AL" COM "assign ldouble (soft-float)\n" " str UR,UL\n", }, -#endif /* assign register to register */ { ASSIGN, FOREFF|INAREG, @@ -921,44 +1067,71 @@ struct optab table[] = { " mov AL,AR" COM "assign UR:AR to UL:AL\n" " mov UL,UR\n", }, -{ ASSIGN, FOREFF|INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, 0, RDEST, -#ifdef ARM_HAS_FPA " mvf AL,AR" COM "assign float reg to float reg\n", }, -#elifdef ARM_HAS_VFP + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, " fcpys AL,AR" COM "assign float reg to float reg\n", }, -#else + +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, " mov AL,AR" COM "assign float reg to float reg\n", }, -#endif -{ ASSIGN, FOREFF|INXREG, - SXREG, TDOUBLE|TLDOUBLE, - SXREG, TDOUBLE|TLDOUBLE, +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, 0, RDEST, -#ifdef ARM_HAS_FPA " mvf AL,AR" COM "assign float reg to float reg\n", }, -#elifdef ARM_HAS_VFP + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, " fcpyd AL,AR" COM "assign float reg to float reg\n", }, -#else + +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, " mov AL,AR" COM "assign (l)double reg to (l)double reg\n" " mov UL,UR\n", }, -#endif -#if 0 { ASSIGN, FOREFF|INAREG, - SFLD, TANY, - SAREG, TANY, - NAREG, RDEST, - "ZE", }, + SFLD, TANY, + SOREG|SNAME, TANY, + 3*NAREG, RDEST, + " ldr A1,AR" COM "bit-field assignment\n" + " ldr A2,AL\n" + " ldr A3,=M\n" + " mov A1,A1,asl H\n" + " and A1,A1,A3\n" + " bic A2,A2,A3\n" + " orr A3,A2,A1\n" + " str A3,AL\n" + "F ldr AD,AR\n" + "FZB", }, -{ ASSIGN, FOREFF, +{ ASSIGN, FOREFF|INAREG, SFLD, TANY, SAREG, TANY, - NAREG, 0, - "ZE", }, -#endif + 3*NAREG, RDEST, + " ldr A2,AL" COM "bit-field assignment\n" + " ldr A3,=M\n" + " mov A1,AR,asl H\n" + " and A1,A1,A3\n" + " bic A2,A2,A3\n" + " orr A3,A2,A1\n" + " str A3,AL\n" + "F mov AD,AR\n" + "FZB", }, { STASG, INAREG|FOREFF, SOREG|SNAME, TANY, @@ -982,41 +1155,59 @@ struct optab table[] = { NSPECIAL|NBREG|NBSL, RESC1, "ZE", }, -{ DIV, INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ DIV, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " dvfs A1,AL,AL" COM "fast (float) divide\n", }, -#elifdef ARM_HAS_VFP + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " fdivs A1,AL,AL" COM "fast (float) divide\n", }, -#else + +{ DIV, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ DIV, INXREG, - SXREG, TDOUBLE, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ DIV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " dvfd A1,AL,AL" COM "double divide\n", }, -#elifdef ARM_HAS_VFP + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " fdivd A1,AL,AL" COM "double divide\n", }, -#else + +{ DIV, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ DIV, INXREG, - SXREG, TLDOUBLE, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA - " dvfe A1,AL,AL" COM "ldouble divide\n", }, -#elifdef ARM_HAS_VFP +{ DIV, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " dvfe A1,AL,AR" COM "long double load\n", }, + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " fdivd A1,AL,AL" COM "double divide\n", }, -#else + +{ DIV, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif { MOD, INAREG, SAREG, TWORD, @@ -1030,68 +1221,110 @@ struct optab table[] = { NSPECIAL|NBREG, RESC1, "ZE", }, +{ MUL, INAREG | FEATURE_MUL, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mul A1,AL,AR\n", }, + { MUL, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NSPECIAL|NAREG, RESC1, - " mul A1,AL,AR\n", }, + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NBREG, RESC1, + " smull U1,A1,AL,AR\n", }, + +{ MUL, INBREG | FEATURE_MUL, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NBREG, RESC1, + " mul A1,AL,AR\n" + " mov U1,A1,asr #31\n", }, { MUL, INBREG, SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, NSPECIAL|NBREG, RESC1, -#ifdef ARM_HAS_MULL - " smull U1,A1,AL,AR\n", }, -#else + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NBREG, RESC1, + " umull U1,A1,AL,AR\n", }, + +{ MUL, INBREG | FEATURE_MUL, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NBREG, RESC1, " mul A1,AL,AR\n" - " mul U1,AL,AR\n", }, -#endif + " mov U1,#0\n", }, { MUL, INBREG, SAREG, TSWORD|TSHORT|TCHAR, SAREG, TSWORD|TSHORT|TCHAR, NSPECIAL|NBREG, RESC1, -#ifdef ARM_HAS_MULL + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, " umull U1,A1,AL,AR\n", }, -#else + +{ MUL, INBREG | FEATURE_MUL, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, " mul A1,AL,AR\n" - " mul U1,AL,AR\n", }, -#endif + " mov U1,A1,asr #31\n", }, { MUL, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NSPECIAL|NBREG, RESC1, -#ifdef ARM_HAS_MULL - " umull U1,A1,AL,AR\n", }, -#else - " mul A1,AL,AR\n" - " mul U1,AL,AR\n", }, -#endif + "ZE", }, -{ MUL, INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ MUL, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " fmls A1,AL,AL" COM "fast (float) multiply\n", }, -#elifdef ARM_HAS_VFP + +{ MUL, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " fmuls A1,AL,AL" COM "float multiply\n", }, -#else + +{ MUL, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ MUL, INXREG, - SXREG, TDOUBLE|TLDOUBLE, - SXREG, TDOUBLE|TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ MUL, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, " mufd A1,AL,AL" COM "fast (l)double multiply\n", }, -#elifdef ARM_HAS_VFP + +{ MUL, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, " muld A1,AL,AL" COM "(l)double multiply\n", }, -#else + +{ MUL, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif /* * Indirection operators. @@ -1115,18 +1348,24 @@ struct optab table[] = { NAREG, RESC1, " ldrb A1,AL" COM "uchar load\n", }, -{ UMUL, INAREG, +{ UMUL, INAREG | FEATURE_HALFWORDS, SANY, TANY, SOREG|SNAME, TUSHORT, NAREG, RESC1, " ldrh A1,AL" COM "short load\n", }, -{ UMUL, INAREG, +{ UMUL, INAREG | FEATURE_HALFWORDS, SANY, TANY, SOREG|SNAME, TSHORT, NAREG, RESC1, " ldrsh A1,AL" COM "short load\n", }, +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TSHORT|TUSHORT, + 2*NAREG|NASL, RESC1, + "ZH", }, + { UMUL, INBREG, SANY, TANY, SOREG|SNAME, TLONGLONG|TULONGLONG, @@ -1134,40 +1373,61 @@ struct optab table[] = { " ldr A1,AL" COM "64-bit load\n" " ldr U1,UL\n", }, -{ UMUL, INFREG, +{ UMUL, INCREG | FEATURE_FPA, SANY, TANY, SOREG|SNAME, TFLOAT, - NFREG, RESC1, -#ifdef ARM_HAS_FPA + NCREG, RESC1, " ldfs A1,AL" COM "float load\n", }, -#elifdef ARM_HAS_VFP -#else + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, " ldr A1,AL" COM "float load\n", }, -#endif -{ UMUL, INXREG, +{ UMUL, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + " ldfd A1,AL" COM "double load\n", }, + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INBREG, SANY, TANY, SOREG|SNAME, TDOUBLE, - NXREG, RESC1, -#ifdef ARM_HAS_FPA - " ldfd AL" COM "double load\n", }, -#elifdef ARM_HAS_VFP -#else + NBREG, RESC1, " ldr A1,AL" COM "double load\n" " ldr U1,UL\n", }, -#endif -{ UMUL, INXREG, +{ UMUL, INCREG | FEATURE_FPA, SANY, TANY, SOREG|SNAME, TLDOUBLE, - NXREG, RESC1, -#ifdef ARM_HAS_FPA - " ldfe AL" COM "long double load\n", }, -#elifdef ARM_HAS_VFP -#else - " ldr A1,AL" COM "long double load\n" + NCREG, RESC1, + " ldfe A1,AL" COM "long double load\n", }, + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "long double load (soft-float)\n" " ldr U1,UL\n", }, -#endif /* * Logical/branching operators @@ -1194,41 +1454,59 @@ struct optab table[] = { 0, RESCC, "ZD", }, -{ OPLOG, FORCC, - SFREG, TFLOAT, - SFREG, TFLOAT, +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, NSPECIAL, RESCC, -#ifdef ARM_HAS_FPA " cmfs AL,AR" COM "float compare\n", }, -#elifdef ARM_HAS_VFP + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RESCC, " fcmps AL,AR" COM "float compare\n", }, -#else - "ZF", }, -#endif { OPLOG, FORCC, - SXREG, TDOUBLE, - SXREG, TDOUBLE, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL, RESCC, + "ZF", }, + +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, NSPECIAL, RESCC, -#ifdef ARM_HAS_FPA " cmfd AL,AR" COM "double compare\n", }, -#elifdef ARM_HAS_VFP + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + 0, RESCC, " fcmpd AL,AR" COM "double compare\n", }, -#else - "ZF", }, -#endif { OPLOG, FORCC, - SXREG, TLDOUBLE, - SXREG, TLDOUBLE, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL, RESCC, + "ZF", }, + +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, NSPECIAL, RESCC, -#ifdef ARM_HAS_FPA " cmfe AL,AR" COM "ldouble compare\n", }, -#elifdef ARM_HAS_VFP + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RESCC, " fcmpd AL,AR" COM "double compare\n", }, -#else + +{ OPLOG, FORCC, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL, RESCC, "ZF", }, -#endif /* AND/OR/ER */ { AND, INBREG, @@ -1311,13 +1589,13 @@ struct optab table[] = { NAREG, RESC1, " ldrb A1,AL" COM "load uchar from memory\n", }, -{ OPLTYPE, INAREG, +{ OPLTYPE, INAREG | FEATURE_HALFWORDS, SANY, TANY, SOREG|SNAME, TSHORT, NAREG, RESC1, " ldrsh A1,AL" COM "load short from memory\n", }, -{ OPLTYPE, INAREG, +{ OPLTYPE, INAREG | FEATURE_HALFWORDS, SANY, TANY, SOREG|SNAME, TUSHORT, NAREG, RESC1, @@ -1325,9 +1603,23 @@ struct optab table[] = { { OPLTYPE, INAREG, SANY, TANY, + SOREG|SNAME, TSHORT|TUSHORT, + 2*NAREG, RESC1, + "ZH", }, + +#if 0 +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TPOINT, + NAREG, RESC1, + " ldr A1,AL" COM "load integer constant\n", }, +#endif + +{ OPLTYPE, INAREG, + SANY, TANY, SCON, TANY, NAREG, RESC1, - " ldr A1,ZI" COM "load integer constant\n", }, + "ZI", }, { OPLTYPE, INBREG, SANY, TANY, @@ -1348,40 +1640,61 @@ struct optab table[] = { " mov A1,AL" COM "load UL:AL into U1:A1\n" " mov U1,UL\n", }, -{ OPLTYPE, INFREG, +{ OPLTYPE, INCREG | FEATURE_FPA, SANY, TANY, SOREG|SNAME, TFLOAT, - NFREG, RESC1, -#ifdef ARM_HAS_FPA + NCREG, RESC1, " ldfs A1,AL" COM "load float\n", }, -#elifdef ARM_HAS_VFP -#else - " ldr A1,AL" COM "load float\n", }, -#endif -{ OPLTYPE, INXREG, +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + COM "not implemented\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, + " ldr A1,AL" COM "load float (soft-float)\n", }, + +{ OPLTYPE, INCREG | FEATURE_FPA, SANY, TANY, SOREG|SNAME, TDOUBLE, - NXREG, RESC1, -#ifdef ARM_HAS_FPA + NCREG, RESC1, " ldfd A1,AL" COM "load double\n", }, -#elifdef ARM_HAS_VFP -#else - " ldr A1,AL" COM "load double\n" + +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + COM "not implemented\n" }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "load double (soft-float)\n" " ldr U1,UL\n", }, -#endif -{ OPLTYPE, INXREG, +{ OPLTYPE, INCREG | FEATURE_FPA, SANY, TANY, SOREG|SNAME, TLDOUBLE, - NXREG, RESC1, -#ifdef ARM_HAS_FPA + NCREG, RESC1, " ldfe A1,AL" COM "load ldouble\n", }, -#elifdef ARM_HAS_VFP -#else - " ldr A1,AL" COM "load ldouble\n" + +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "load ldouble (soft-float)\n" " ldr U1,UL\n", }, -#endif /* * Negate a word. @@ -1391,7 +1704,7 @@ struct optab table[] = { SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, - " neg A1,AL" COM "negation\n", }, + " rsb A1,AL,#0" COM "negation\n", }, { UMINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, @@ -1400,41 +1713,59 @@ struct optab table[] = { " rsbs A1,AL,#0" COM "64-bit negation\n" " rsc U1,UL,#0\n", }, -{ UMINUS, INFREG, - SFREG, TFLOAT, - SFREG, TFLOAT, - NSPECIAL|NFREG, RESC1, -#ifdef ARM_HAS_FPA +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " mvfs A1,AL" COM "float negation\n", }, -#elifdef ARM_HAS_VFP + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, " negs A1,AL" COM "float negation\n", }, -#else + +{ UMINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, "ZF", }, -#endif -{ UMINUS, INXREG, - SXREG, TDOUBLE, - SXREG, TDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " mvfd A1,AL" COM "double negation\n", }, -#elifdef ARM_HAS_VFP + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, " negd A1,AL" COM "double negation\n", }, -#else + +{ UMINUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif -{ UMINUS, INXREG, - SXREG, TLDOUBLE, - SXREG, TLDOUBLE, - NSPECIAL|NXREG, RESC1, -#ifdef ARM_HAS_FPA +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " mvfe A1,AL" COM "ldouble negation\n", }, -#elifdef ARM_HAS_VFP + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, " negd A1,AL" COM "ldouble negation\n", }, -#else + +{ UMINUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, "ZF", }, -#endif { COMPL, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, @@ -1466,13 +1797,13 @@ struct optab table[] = { " stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", }, { FUNARG, FOREFF, - SFREG, TFLOAT, + SCREG, TFLOAT, SANY, TFLOAT, 0, 0, " stmfd sp!,{AL}" COM "save function arg to stack\n", }, { FUNARG, FOREFF, - SXREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, SANY, TDOUBLE|TLDOUBLE, 0, 0, " stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", }, diff --git a/usr.bin/pcc/cc/cc.1 b/usr.bin/pcc/cc/cc.1 index 0fe730b2a10..75841c134a2 100644 --- a/usr.bin/pcc/cc/cc.1 +++ b/usr.bin/pcc/cc/cc.1 @@ -1,31 +1,32 @@ -.\" $OpenBSD: cc.1,v 1.3 2007/10/16 13:46:30 stefan Exp $ +.\" $OpenBSD: cc.1,v 1.4 2008/04/11 20:45:52 stefan Exp $ .\" .\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net> -.\" -.\" Permission to use, copy, modify, and/or distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM -.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND -.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF .\" THIS SOFTWARE. .\" .Dd September 14, 2007 -.Dt cc 1 +.Dt CC 1 .Os .Sh NAME .Nm cc .Nd front-end to the C compiler .Sh SYNOPSIS .Nm -.Op Fl cEgkLMPOStvxX +.Op Fl cEgkLMPOStvXx .Op Fl fPIC .Op Fl fpic +.Op Fl m Ns Ar option .Op Fl nostartfiles .Op Fl nostdinc .Op Fl nostdlib @@ -41,12 +42,11 @@ .Op Fl o Ar outfile .Op Fl Wl Ar flags .Op Ar -.Pp .Sh DESCRIPTION The .Nm utility provides a front-end to the -.Dq portable C compiler. +.Dq portable C compiler . Multiple files may be given on the command line. Unrecognized options are all sent directly to .Xr ld 1 . @@ -55,22 +55,22 @@ Unrecognized options are all sent directly to Filenames that end with .Sy \&.c are passed via -.Xr cpp 1 -> -.Xr ccom 1 -> -.Xr as 1 -> +.Xr cpp 1 -\*[Gt] +.Xr ccom 1 -\*[Gt] +.Xr as 1 -\*[Gt] .Xr ld 1 . .Pp Filenames that end with .Sy \&.i are passed via -.Xr ccom 1 -> -.Xr as 1 -> +.Xr ccom 1 -\*[Gt] +.Xr as 1 -\*[Gt] .Xr ld 1 . .Pp Filenames that end with .Sy \&.s are passed via -.Xr as 1 -> +.Xr as 1 -\*[Gt] .Xr ld 1 . .Pp Filenames that end with @@ -99,7 +99,7 @@ Only compile or assemble and then stop. Do not link. The resulting object output is saved as a filename with a -.Dq .o +.Dq \&.o suffix unless .Fl o option is used. @@ -146,7 +146,7 @@ Passed to the preprocessor to add header search directory to override system defaults. .It Fl include Ar file Tells the -.Xr cpp 1 +.Xr cpp 1 preprocessor to include the .Ar file during preprocessing. @@ -162,7 +162,7 @@ See .Fl fpic option. .It Fl L -.\" TODO +TODO .It Fl M Pass .Fl M @@ -170,12 +170,26 @@ flag to .Xr cpp 1 to generate dependencies for .Xr make 1 . +.It Fl m Ns options +Target-dependent option. +.Bl -tag -width PowerPC +.It ARM +-mlittle-endian -mbig-endian -mfpe=fpa -mfpe=vpf -msoft-float -march=armv1 -march=armv2 -march=armv2a -march=armv3 -march=armv4 -march=armv4t -march=armv4tej -march=armv5 -march=armv6 -march=armv6t2 -march=armv6kz -march=armv6k -march=armv7 +.It HPPA +.It i386 +.It MIPS +-mlittle-endian -mbig-endian -mhard-float -msoft-float +.It PDP-10 +.It PowerPC +.It Sparc64 +.It VAX +.El .It Fl nostartfiles -.\" TODO +Do not link with the system startup files (crt0.c, etc.) .It Fl nostdinc -.\" TODO +Do not use the system include paths (/usr/include, etc.) .It Fl nostdlib -.\" TODO +Do not link with the system C library (libc). .\" implies -nostartfiles ?? .It Fl O Enable optimizations. @@ -185,17 +199,18 @@ and .Fl xtemps to .Xr ccom 1 . -Note: this is unset if +Note: this is unset if the .Fl g -option is set. +option is used. .It Fl o Ar outfile Save result to .Ar outfile . .It Fl P -TODO: what is this? +TODO +.\" TODO: what is this? .\" TODO: Looks like it does cpp only, but I couldn't get it to work for me. .It Fl pg -Not implemented. +Enable profiling on the generated executable. .It Fl pthread Defines .Sy _PTHREADS @@ -203,15 +218,16 @@ preprocessor directive for .Xr cpp 1 . Uses .Sy -lpthread -for -.Xr ld 1 linker. +for the +.Xr ld 1 +linker. .It Fl S Stop after compilation by .Xr ccom 1 . Do not assemble and do not link. The resulting assembler-language output is saved as a filename with a -.Dq .s +.Dq \&.s suffix unless the .Fl o option is used. @@ -229,22 +245,22 @@ to .Xr cpp 1 for traditional C preprocessor syntax. .It Fl U Ar macro -Passes to the +Passes to the .Xr cpp 1 preprocessor to remove the initial macro definition. .It Fl v Outputs the version of .Nm -and shows what commands will be ran with their command line arguments. +and shows what commands will be run with their command line arguments. .It Fl Wl Ar flags -Options for the linker +Options for the linker. .\" what is ignored? llist? .It Fl X Don't remove temporary files on exit. .It Fl x TODO .El -.Sh Predefined Macros +.Ss Predefined Macros A few macros are predefined by .Nm @@ -260,7 +276,7 @@ Set to the major version of These macros can be used to select code based on .Xr pcc 1 compatibility. -See +See the .Fl v option. .It __PCC_MINOR__ @@ -287,8 +303,8 @@ and .Sh HISTORY The .Nm -command comes from the original Portable C Compiler by S. C. -Johnson, written in the late 70's. +command comes from the original Portable C Compiler by S. C. Johnson, +written in the late 70's. .Pp This product includes software developed or owned by Caldera International, Inc. diff --git a/usr.bin/pcc/cc/cc.c b/usr.bin/pcc/cc/cc.c index 5d57d542369..23cf8beb7a8 100644 --- a/usr.bin/pcc/cc/cc.c +++ b/usr.bin/pcc/cc/cc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cc.c,v 1.12 2007/11/22 21:47:24 stefan Exp $ */ +/* $OpenBSD: cc.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -96,6 +96,9 @@ char *llist[MAXLIB]; char alist[20]; char *xlist[100]; int xnum; +char *mlist[100]; +char *idirafter; +int nm; int Cflag; int dflag; int pflag; @@ -114,6 +117,7 @@ int Mflag; /* dependencies only */ int pgflag; int exfail; int Xflag; +int Werror; int nostartfiles, Bstatic; int nostdinc, nostdlib; int onlyas; @@ -125,6 +129,7 @@ char *Bflag; char *cppadd[] = CPPADD; char *dynlinker[] = DYNLINKER; char *crt0file = CRT0FILE; +char *crt0file_profile = CRT0FILE_PROFILE; char *startfiles[] = STARTFILES; char *endfiles[] = ENDFILES; char *mach = DEFMACH; @@ -139,6 +144,11 @@ char *libclibs[] = LIBCLIBS; #else char *libclibs[] = { "-lc", NULL }; #endif +#ifdef LIBCLIBS_PROFILE +char *libclibs_profile[] = LIBCLIBS_PROFILE; +#else +char *libclibs_profile[] = { "-lc_p", NULL }; +#endif #ifndef STARTLABEL #define STARTLABEL "__start" #endif @@ -158,7 +168,12 @@ main(int argc, char *argv[]) switch (argv[i][1]) { default: goto passa; - +#ifdef notyet + /* must add library options first (-L/-l/...) */ + error("unrecognized option `-%c'", argv[i][1]); + break; +#endif + case 'B': /* other search paths for binaries */ Bflag = &argv[i][2]; break; @@ -190,7 +205,9 @@ main(int argc, char *argv[]) Xflag++; break; case 'W': /* Ignore (most of) W-flags */ - if (strncmp(argv[i], "-Wl,", 4) == 0) { + if (strncmp(argv[i], "-Werror", 7) == 0) { + Werror = 1; + } else if (strncmp(argv[i], "-Wl,", 4) == 0) { /* options to the linker */ t = &argv[i][4]; while ((u = strchr(t, ','))) { @@ -199,9 +216,13 @@ main(int argc, char *argv[]) t = u; } llist[nl++] = t; + } else if (strncmp(argv[i], "-Wp,", 4) == 0) { + /* preprocessor */ + if (!strncmp(argv[i], "-Wp,-C", 6)) + Cflag++; } break; - + case 'f': /* GCC compatibility flags */ if (strcmp(argv[i], "-fPIC") == 0) kflag = F_PIC; @@ -209,11 +230,11 @@ main(int argc, char *argv[]) kflag = F_pic; /* silently ignore the rest */ break; - + case 'g': /* create debug output */ gflag++; break; - + case 'i': if (strcmp(argv[i], "-isystem") == 0) { *pv++ = "-S"; @@ -221,14 +242,20 @@ main(int argc, char *argv[]) } else if (strcmp(argv[i], "-include") == 0) { *pv++ = "-i"; *pv++ = argv[++i]; + } else if (strcmp(argv[i], "-idirafter") == 0) { + idirafter = argv[++i]; } else goto passa; break; - + case 'k': /* generate PIC code */ kflag = F_pic; break; - + + case 'm': /* target-dependent options */ + mlist[nm++] = argv[i]; + break; + case 'n': /* handle -n flags */ if (strcmp(argv[i], "-nostdinc") == 0) nostdinc++; @@ -240,7 +267,7 @@ main(int argc, char *argv[]) else goto passa; break; - + case 'p': if (strcmp(argv[i], "-pg") == 0) pgflag++; @@ -251,9 +278,19 @@ main(int argc, char *argv[]) else errorx(1, "unknown option %s", argv[i]); break; - + case 'x': - xlist[xnum++] = argv[i]; + t = &argv[i][2]; + if (*t == 0) + t = argv[++i]; + if (strcmp(t, "c") == 0) + ; /* default */ +#ifdef notyet + else if (strcmp(t, "c++")) + cxxflag; +#endif + else + xlist[xnum++] = argv[i]; break; case 't': tflag++; @@ -279,7 +316,7 @@ main(int argc, char *argv[]) case 'c': cflag++; break; - + #if 0 case '2': if(argv[i][2] == '\0') @@ -298,17 +335,16 @@ main(int argc, char *argv[]) *pv++ = argv[i]; if (argv[i][2] == 0) *pv++ = argv[++i]; - if (pv >= ptemp+MAXOPT) - { + if (pv >= ptemp+MAXOPT) { error("Too many DIU options"); --pv; } break; - + case 'M': Mflag++; break; - + case 'd': dflag++; strlcpy(alist, argv[i], sizeof (alist)); @@ -317,7 +353,7 @@ main(int argc, char *argv[]) printf("%s\n", VERSSTR); vflag++; break; - + case 's': if (strcmp(argv[i], "-static") == 0) Bstatic = 1; @@ -333,11 +369,10 @@ main(int argc, char *argv[]) else if((c=getsuf(t))=='c' || c=='S' || c=='i' || c=='s'|| Eflag) { clist[nc++] = t; - if (nc>=MAXFIL) - { + if (nc>=MAXFIL) { error("Too many source files"); exit(1); - } + } t = setsuf(t, 'o'); } @@ -348,11 +383,10 @@ main(int argc, char *argv[]) } if (j == nl) { llist[nl++] = t; - if (nl >= MAXLIB) - { + if (nl >= MAXLIB) { error("Too many object/library files"); exit(1); - } + } if (getsuf(t)=='o') nxo++; } @@ -434,6 +468,10 @@ main(int argc, char *argv[]) av[na++] = *pv; if (!nostdinc) av[na++] = "-S", av[na++] = STDINC; + if (idirafter) { + av[na++] = "-I"; + av[na++] = idirafter; + } av[na++] = clist[i]; if (!Eflag && !Mflag) av[na++] = tmp4; @@ -457,16 +495,22 @@ main(int argc, char *argv[]) av[na++]= "ccom"; if (vflag) av[na++] = "-v"; + if (pgflag) + av[na++] = "-p"; if (gflag) av[na++] = "-g"; if (kflag) av[na++] = "-k"; + if (Werror) + av[na++] = "-Werror"; if (Oflag) { av[na++] = "-xtemps"; av[na++] = "-xdeljumps"; } for (j = 0; j < xnum; j++) av[na++] = xlist[j]; + for (j = 0; j < nm; j++) + av[na++] = mlist[j]; if (getsuf(clist[i])=='i') av[na++] = clist[i]; else @@ -554,6 +598,7 @@ nocom: } if (!nostartfiles) { av[j++] = crt0file; + av[j++] = pgflag ? crt0file_profile : crt0file; for (i = 0; startfiles[i]; i++) av[j++] = startfiles[i]; } @@ -571,9 +616,17 @@ nocom: #endif if (pthreads) av[j++] = "-lpthread"; - if (!nostdlib) + if (!nostdlib) { + if (pgflag) { + for (i = 0; libclibs_profile[i]; i++) + av[j++] = libclibs_profile[i]; + } else { + for (i = 0; libclibs[i]; i++) + av[j++] = libclibs[i]; + } for (i = 0; libclibs[i]; i++) av[j++] = libclibs[i]; + } if (!nostartfiles) { for (i = 0; endfiles[i]; i++) av[j++] = endfiles[i]; diff --git a/usr.bin/pcc/ccconfig.h b/usr.bin/pcc/ccconfig.h index 24cbd11f762..c7fe0569ba6 100644 --- a/usr.bin/pcc/ccconfig.h +++ b/usr.bin/pcc/ccconfig.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ccconfig.h,v 1.3 2007/10/22 13:40:08 otto Exp $ */ +/* $OpenBSD: ccconfig.h,v 1.4 2008/04/11 20:45:51 stefan Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -35,6 +35,7 @@ #define CPPADD { "-D__OpenBSD__", "-D__unix__", NULL } #define DYNLINKER { "-dynamic-linker", "/usr/libexec/ld.so", NULL } #define CRT0FILE "/usr/lib/crt0.o" +#define CRT0FILE_PROFILE "/usr/lib/gcrt0.o" #define STARTFILES { "/usr/lib/crtbegin.o", NULL } #define ENDFILES { "/usr/lib/crtend.o", NULL } diff --git a/usr.bin/pcc/ccom/ccom.1 b/usr.bin/pcc/ccom/ccom.1 index fee05e09a80..bc7a642b821 100644 --- a/usr.bin/pcc/ccom/ccom.1 +++ b/usr.bin/pcc/ccom/ccom.1 @@ -1,20 +1,20 @@ -.\" $OpenBSD: ccom.1,v 1.2 2007/10/20 18:23:35 otto Exp $ +.\" $OpenBSD: ccom.1,v 1.3 2008/04/11 20:45:52 stefan Exp $ ."\ .\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net> -.\" Permission to use, copy, modify, and/or distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM -.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND -.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF .\" THIS SOFTWARE. .Dd September 14, 2007 -.Dt ccom 1 +.Dt CCOM 1 .Os .Sh NAME .Nm ccom @@ -28,14 +28,15 @@ .Op Fl Z Ar flags .Op infile .Op outfile -.Pp .Sh DESCRIPTION The .Nm utility provides a C compiler. The frontend is usually .Xr pcc 1 . -It is \fBnot\fR intended to be run directly. +It is +.Em not +intended to be run directly. .Pp .Nm reads the C source from @@ -65,23 +66,28 @@ Display version. .It Fl W Ar flags Report warnings. (Do some basic checks.) -NOTE! These are subject to change RSN! +.Em NOTE! +.Em These are subject to change RSN! .Ar flags is one or more of the following: .Bl -tag -width Ds +.It Sy error +Report all warnings as errors. .It Sy implicit Implies .Sy implicit-function-declaration and .Sy implicit-int . .It Sy implicit-function-declaration -Report if no prototype for function. +Report if no prototype was declared for a function. .It Sy implicit-int TODO .It Sy missing-prototypes TODO .It Sy strict-prototypes TODO +.It Sy W +Enable all warnings. .El .\" .It Fl X Ar flags @@ -92,7 +98,7 @@ is one or more of the following: .It Sy b Building of parse trees .It Sy d -Declarations (multiple +Declarations (using multiple .Sy d flags gives more output) .It Sy e @@ -115,23 +121,27 @@ Target-specific flag, used in machine-dependent code .\" .It Fl x Ar optimizations .Ar optimizations -is one or more of the following: +is one of the following: .\" TODO: reword this, since multiple terms don't go with one -x switch?? .Bl -tag -width deljumps .It Sy deljumps Delete redundant jumps and dead code. .It Sy ssa -Convert statements into SSA form for optimization. Not yet finished. +Convert statements into SSA form for optimization. +Not yet finished. .It Sy tailcall Currently not implemented. .It Sy temps -Setting this flag allows variables to be put into registers, for further +Setting this flag allows variables to be put into registers, for further optimization by the register allocator. .El +The +.Fl x +flag can be passed multiple times to set different options. .\" .It Fl Z Ar flags Code generator (pass2) specific debugging where -.Ar flags +.Ar flags is one or more of the following: .Bl -tag -width Ds .It Sy b @@ -155,7 +165,7 @@ Type matching in instruction generator .It Sy u Sethi-Ullman computations .It Sy x -Target-specific flag, used in machine-dependent code +Target-specific flag, used in machine-dependent code .El .El .Sh SEE ALSO @@ -165,8 +175,8 @@ Target-specific flag, used in machine-dependent code .Sh HISTORY The .Nm -compiler is based on the original Portable C Compiler by S. C. -Johnson, written in the late 70's. +compiler is based on the original Portable C Compiler by S. C. Johnson, +written in the late 70's. Even though much of the compiler has been rewritten, some of the basics still remain. About 50% of the frontend code and 80% of the backend code has been @@ -174,7 +184,7 @@ rewritten. Most is written by Anders Magnusson, with the exception of the data-flow analysis part and the SSA conversion code which is written by Peter A Jonsson, and the Mips port that were written as -part of a project by undergraduate students at Lulea University of +part of a project by undergraduate students at Lulea University of Technology. .Pp This product includes software developed or owned by Caldera diff --git a/usr.bin/pcc/ccom/cgram.y b/usr.bin/pcc/ccom/cgram.y index 79c1a3963e7..2af2844b3aa 100644 --- a/usr.bin/pcc/ccom/cgram.y +++ b/usr.bin/pcc/ccom/cgram.y @@ -1,4 +1,4 @@ -/* $OpenBSD: cgram.y,v 1.8 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: cgram.y,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -147,7 +147,9 @@ static int fun_inline; /* Reading an inline function */ int oldstyle; /* Current function being defined */ int noretype; static struct symtab *xnf; -extern int enummer; +extern int enummer, tvaloff; +extern struct rstack *rpole; +static int ctval; static NODE *bdty(int op, ...); static void fend(void); @@ -161,9 +163,14 @@ static void adddef(void); static void savebc(void); static void swstart(int, TWORD); static void genswitch(int, TWORD, struct swents **, int); -static NODE * structref(NODE *p, int f, char *name); +static NODE *structref(NODE *p, int f, char *name); static char *mkpstr(char *str); static struct symtab *clbrace(NODE *); +static NODE *cmop(NODE *l, NODE *r); +static NODE *xcmop(NODE *out, NODE *in, NODE *str); +static void mkxasm(char *str, NODE *p); +static NODE *xasmop(char *str, NODE *p); + /* * State for saving current switch state (when nested switches). @@ -198,7 +205,7 @@ struct savbc { declaration_specifiers pointer direct_abstract_declarator specifier_qualifier_list merge_specifiers nocon_e identifier_list arg_param_list arg_declaration arg_dcl_list - designator_list designator + designator_list designator xasm oplist oper cnstr %type <strp> string wstring C_STRING C_WSTRING %type <rp> str_head %type <symp> xnfdeclarator clbrace enum_head @@ -328,6 +335,9 @@ type_qualifier_list: direct_declarator: C_NAME { $$ = bdty(NAME, $1); } | '(' declarator ')' { $$ = $2; } | direct_declarator '[' nocon_e ']' { + $3 = optim($3); + if (blevel == 0 && !nncon($3)) + uerror("array size not constant"); if (!ISINTEGER($3->n_type)) werror("array size is not an integer"); else if ($3->n_op == ICON && $3->n_lval < 0) { @@ -337,32 +347,43 @@ direct_declarator: C_NAME { $$ = bdty(NAME, $1); } $$ = block(LB, $1, $3, INT, 0, MKSUE(INT)); } | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); } - | direct_declarator '(' notype parameter_type_list ')' { + | direct_declarator '(' fundcl parameter_type_list ')' { + if (blevel-- > 1) + symclear(blevel); $$ = bdty(CALL, $1, $4); } - | direct_declarator '(' notype identifier_list ')' { + | direct_declarator '(' fundcl identifier_list ')' { + if (blevel-- > 1) + symclear(blevel); $$ = bdty(CALL, $1, $4); if (blevel != 0) uerror("function declaration in bad context"); oldstyle = 1; } - | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); } + | direct_declarator '(' ')' { + ctval = tvaloff; + $$ = bdty(UCALL, $1); + } ; -notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ } +fundcl: { if (++blevel == 1) argoff = ARGINIT; ctval = tvaloff; } ; -identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; } +identifier_list: C_NAME { + $$ = mkty(FARG, NULL, MKSUE(INT)); + $$->n_sp = lookup($1, 0); + defid($$, PARAM); + } | identifier_list ',' C_NAME { - $$ = bdty(NAME, $3); - $$->n_type = FARG; + $$ = mkty(FARG, NULL, MKSUE(INT)); + $$->n_sp = lookup($3, 0); + defid($$, PARAM); $$ = block(CM, $1, $$, 0, 0, 0); } ; /* * Returns as parameter_list, but can add an additional ELLIPSIS node. - * Calls revert() to get the parameter list in the forward order. */ parameter_type_list: parameter_list { $$ = $1; } @@ -388,8 +409,18 @@ parameter_list: parameter_declaration { $$ = $1; } */ parameter_declaration: declaration_specifiers declarator { + if ($1->n_lval == AUTO || $1->n_lval == TYPEDEF || + $1->n_lval == EXTERN || $1->n_lval == STATIC) + uerror("illegal parameter class"); $$ = tymerge($1, $2); + if (blevel == 1) { + $$->n_sp = lookup((char *)$$->n_sp, 0);/* XXX */ + if (ISFTN($$->n_type)) + $$->n_type = INCREF($$->n_type); + defid($$, PARAM); + } nfree($1); + } | declaration_specifiers abstract_declarator { $$ = tymerge($1, $2); @@ -418,14 +449,14 @@ direct_abstract_declarator: $$ = bdty(LB, $1, $3); } | '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); } - | '(' notype parameter_type_list ')' { - $$ = bdty(CALL, bdty(NAME, NULL), $3); + | '(' parameter_type_list ')' { + $$ = bdty(CALL, bdty(NAME, NULL), $2); } | direct_abstract_declarator '(' ')' { $$ = bdty(UCALL, $1); } - | direct_abstract_declarator '(' notype parameter_type_list ')' { - $$ = bdty(CALL, $1, $4); + | direct_abstract_declarator '(' parameter_type_list ')' { + $$ = bdty(CALL, $1, $3); } ; @@ -496,14 +527,15 @@ moe_list: moe ; moe: C_NAME { moedef($1); } + | C_TYPENAME { moedef($1); } | C_NAME '=' con_e { enummer = $3; moedef($1); } + | C_TYPENAME '=' con_e { enummer = $3; moedef($1); } ; struct_dcl: str_head '{' struct_dcl_list '}' empty { $$ = dclstruct($1); } | C_STRUCT C_NAME { $$ = rstruct($2,$1); } - | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); } | str_head '{' '}' { #ifndef GCC_COMPAT werror("gcc extension"); @@ -518,7 +550,6 @@ empty: { /* Get yacc read the next token before reducing */ } str_head: C_STRUCT { $$ = bstruct(NULL, $1); } | C_STRUCT C_NAME { $$ = bstruct($2,$1); } - | C_STRUCT C_TYPENAME { $$ = bstruct($2,$1); } ; struct_dcl_list: struct_declaration @@ -549,30 +580,21 @@ struct_declarator_list: struct_declarator: declarator { tymerge($<nodep>0, $1); - $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */ - defid($1, $<nodep>0->n_lval); + soumemb($1, (char *)$1->n_sp, + $<nodep>0->n_lval); /* XXX */ nfree($1); } | ':' con_e { - if (!(instruct&INSTRUCT)) - uerror( "field outside of structure" ); - if ($2 < 0 || $2 >= FIELD) { - uerror("illegal field size"); + if (fldchk($2)) $2 = 1; - } falloc(NULL, $2, -1, $<nodep>0); } | declarator ':' con_e { - if (!(instruct&INSTRUCT)) - uerror( "field outside of structure" ); - if( $3<0 || $3 >= FIELD ){ - uerror( "illegal field size" ); + if (fldchk($3)) $3 = 1; - } if ($1->n_op == NAME) { tymerge($<nodep>0, $1); - $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME); - defid($1, FIELD|$3); + soumemb($1, (char *)$1->n_sp, FIELD | $3); nfree($1); } else uerror("illegal declarator"); @@ -632,7 +654,11 @@ designator: '[' con_e ']' { } $$ = bdty(LB, NULL, $2); } - | C_STROP C_NAME { $$ = bdty(NAME, $2); } + | C_STROP C_NAME { + if ($1 != DOT) + uerror("invalid designator"); + $$ = bdty(NAME, $2); + } ; optcomma : /* VOID */ @@ -696,7 +722,7 @@ begin: '{' { } ; -statement: e ';' { ecomp( $1 ); } +statement: e ';' { ecomp( $1 ); symclear(blevel); } | compoundstmt | ifprefix statement { plabel($1); reached = 1; } | ifelprefix statement { @@ -799,8 +825,26 @@ statement: e ';' { ecomp( $1 ); } ; asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); } + | C_ASM '(' string xasm ')' { mkxasm($3, $4); } + ; + +xasm: ':' oplist { $$ = xcmop($2, NIL, NIL); } + | ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); } + | ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); } + ; + +oplist: /* nothing */ { $$ = NIL; } + | oper { $$ = $1; } ; +oper: string '(' e ')' { $$ = xasmop($1, $3); } + | oper ',' string '(' e ')' { $$ = cmop($1, xasmop($3, $5)); } + ; + +cnstr: string { $$ = xasmop($1, bcon(0)); } + | cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); } + ; + label: C_NAME ':' { deflabel($1); reached = 1; } | C_CASE e ':' { addcase($2); reached = 1; } | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; } @@ -861,7 +905,23 @@ forprefix: C_FOR '(' .e ';' .e ';' { else flostat |= FLOOP; } + | C_FOR '(' incblev declaration .e ';' { + blevel--; + savebc(); + contlab = getlab(); + brklab = getlab(); + plabel( $$ = getlab()); + reached = 1; + if ($5) + cbranch(buildtree(NOT, $5, NIL), bcon(brklab)); + else + flostat |= FLOOP; + } ; + +incblev: { blevel++; } + ; + switchpart: C_SWITCH '(' e ')' { NODE *p; int num; @@ -887,14 +947,14 @@ switchpart: C_SWITCH '(' e ')' { } ; /* EXPRESSIONS */ -con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' { - $$ = icons( $2 ); - instruct=$<intval>1; +con_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' { + $$ = icons($2); + rpole = $<rp>1; } ; -nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' { - instruct=$<intval>1; +nocon_e: { $<rp>$ = rpole; rpole = NULL; } e %prec ',' { + rpole = $<rp>1; $$ = $2; } ; @@ -979,7 +1039,7 @@ term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); } | C_SIZEOF '(' cast_type ')' %prec C_SIZEOF { $$ = doszof($3); } - | '(' cast_type ')' clbrace init_list '}' { + | '(' cast_type ')' clbrace init_list optcomma '}' { endinit(); spname = $4; $$ = buildtree(NAME, NIL, NIL); @@ -1294,6 +1354,8 @@ init_declarator(NODE *tn, NODE *p, int assign) if (assign) { defid(typ, class); typ->n_sp->sflags |= SASG; + if (typ->n_sp->sflags & SDYNARRAY) + uerror("can't initialize dynamic arrays"); lcommdel(typ->n_sp); } else { nidcl(typ, class); @@ -1315,10 +1377,18 @@ fundef(NODE *tp, NODE *p) { extern int prolab; struct symtab *s; + NODE *q = p; int class = tp->n_lval, oclass; char *c; - /* Enter function args before they are clobbered in tymerge() */ + while (q->n_op == UMUL) + q = q->n_left; + if (q->n_op != CALL && q->n_op != UCALL) { + uerror("invalid function definition"); + p = bdty(UCALL, p); + } + + /* Save function args before they are clobbered in tymerge() */ /* Typecheck against prototype will be done in defid(). */ ftnarg(p); @@ -1344,8 +1414,8 @@ fundef(NODE *tp, NODE *p) prolab = getlab(); c = cftnsp->soname; send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype, - cftnsp->sclass == EXTDEF, prolab); - blevel = 1; + cftnsp->sclass == EXTDEF, prolab, ctval); + blevel++; #ifdef STABS if (gflag) stabs_func(s); @@ -1409,9 +1479,10 @@ static char * mkpstr(char *str) { char *s, *os; - int v, l = strlen(str)+1; + int v, l = strlen(str)+3; /* \t + \n + \0 */ os = s = isinlining ? permalloc(l) : tmpalloc(l); + *s++ = '\t'; for (; *str; ) { if (*str++ == '\\') v = esccon(&str); @@ -1419,6 +1490,7 @@ mkpstr(char *str) v = str[-1]; *s++ = v; } + *s++ = '\n'; *s = 0; return os; } @@ -1445,3 +1517,90 @@ clbrace(NODE *p) beginit(sp); return sp; } + +/* Support for extended assembler a' la' gcc style follows below */ + +static NODE * +cmop(NODE *l, NODE *r) +{ + return block(CM, l, r, INT, 0, MKSUE(INT)); +} + +static NODE * +voidcon(void) +{ + return block(ICON, NIL, NIL, STRTY, 0, MKSUE(VOID)); +} + +static NODE * +xmrg(NODE *out, NODE *in) +{ + NODE *p = in; + + if (p->n_op == XARG) { + in = cmop(out, p); + } else { + while (p->n_left->n_op == CM) + p = p->n_left; + p->n_left = cmop(out, p->n_left); + } + return in; +} + +/* + * Put together in and out node lists in one list, and balance it with + * the constraints on the right side of a CM node. + */ +static NODE * +xcmop(NODE *out, NODE *in, NODE *str) +{ + NODE *p, *q; + + if (out) { + /* D out-list sanity check */ + for (p = out; p->n_op == CM; p = p->n_left) { + q = p->n_right; + if (q->n_name[0] != '=') + uerror("output missing ="); + } + if (p->n_name[0] != '=') + uerror("output missing ="); + if (in == NIL) + p = out; + else + p = xmrg(out, in); + } else if (in) { + p = in; + } else + p = voidcon(); + + if (str == NIL) + str = voidcon(); + return cmop(p, str); +} + +/* + * Generate a XARG node based on a string and an expression. + */ +static NODE * +xasmop(char *str, NODE *p) +{ + + p = block(XARG, p, NIL, INT, 0, MKSUE(INT)); + p->n_name = str; + return p; +} + +/* + * Generate a XASM node based on a string and an expression. + */ +static void +mkxasm(char *str, NODE *p) +{ + NODE *q; + + q = block(XASM, p->n_left, p->n_right, INT, 0, MKSUE(INT)); + q->n_name = str; + nfree(p); + ecomp(q); +} diff --git a/usr.bin/pcc/ccom/gcc_compat.c b/usr.bin/pcc/ccom/gcc_compat.c index 4148cd4ead4..1f8920623e6 100644 --- a/usr.bin/pcc/ccom/gcc_compat.c +++ b/usr.bin/pcc/ccom/gcc_compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gcc_compat.c,v 1.4 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: gcc_compat.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -50,6 +50,7 @@ static struct kw { { "__const", NULL, 0 }, { "__asm__", NULL, C_ASM }, { "__inline__", NULL, C_FUNSPEC }, + { "__thread", NULL, 0 }, { NULL, NULL, 0 }, }; @@ -63,12 +64,15 @@ gcc_init() } +#define TS "\n#pragma tls\n# %d\n" +#define TLLEN sizeof(TS)+10 /* * See if a string matches a gcc keyword. */ int gcc_keyword(char *str, NODE **n) { + char tlbuf[TLLEN], *tw; struct kw *kwp; int i; @@ -86,6 +90,12 @@ gcc_keyword(char *str, NODE **n) case 3: /* __const */ *n = block(QUALIFIER, NIL, NIL, CON, 0, 0); return C_QUALIFIER; + case 6: /* __thread */ + snprintf(tlbuf, TLLEN, TS, lineno); + tw = &tlbuf[strlen(tlbuf)]; + while (tw > tlbuf) + cunput(*--tw); + return -1; } cerror("gcc_keyword"); return 0; diff --git a/usr.bin/pcc/ccom/init.c b/usr.bin/pcc/ccom/init.c index 8e800c84cb9..f4ced795f23 100644 --- a/usr.bin/pcc/ccom/init.c +++ b/usr.bin/pcc/ccom/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.6 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: init.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se). @@ -118,8 +118,8 @@ int idebug; */ static struct instk { struct instk *in_prev; /* linked list */ - struct symtab **in_xp; /* member in structure initializations */ - struct symtab *in_sym; /* stab index */ + struct symtab *in_lnk; /* member in structure initializations */ + struct symtab *in_sym; /* symtab index */ union dimfun *in_df; /* dimenston of array */ TWORD in_t; /* type for this level */ int in_n; /* number of arrays seen so far */ @@ -231,7 +231,7 @@ beginit(struct symtab *sp) curll = ll = getll(); /* at least first entry in list */ /* first element */ - is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL; + is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL; is->in_n = 0; is->in_t = sp->stype; is->in_sym = sp; @@ -279,22 +279,22 @@ stkpush(void) is->in_n = 0; if (pstk == NULL) { /* stack empty */ - is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL; + is->in_lnk = ISSOU(sp->stype) ? sp->ssue->sylnk : NULL; is->in_t = sp->stype; is->in_sym = sp; is->in_df = sp->sdf; } else if (ISSOU(t)) { - sq = *pstk->in_xp; + sq = pstk->in_lnk; if (sq == NULL) { uerror("excess of initializing elements"); } else { - is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0; + is->in_lnk = ISSOU(sq->stype) ? sq->ssue->sylnk : 0; is->in_t = sq->stype; is->in_sym = sq; is->in_df = sq->sdf; } } else if (ISARY(t)) { - is->in_xp = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->suelem : 0; + is->in_lnk = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->sylnk : 0; is->in_t = DECREF(t); is->in_sym = sp; if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) { @@ -329,9 +329,9 @@ stkpop(void) printf("stkpop\n"); #endif for (; pstk; pstk = pstk->in_prev) { - if (pstk->in_t == STRTY && pstk->in_xp[0] != NULL) { - pstk->in_xp++; - if (*pstk->in_xp != NULL) + if (pstk->in_t == STRTY && pstk->in_lnk != NULL) { + pstk->in_lnk = pstk->in_lnk->snext; + if (pstk->in_lnk != NULL) break; } if (ISSOU(pstk->in_t) && pstk->in_fl) @@ -716,8 +716,9 @@ irbrace() if (ISARY(pstk->in_t)) pstk->in_n = pstk->in_df->ddim; else if (pstk->in_t == STRTY) { - while (pstk->in_xp[0] != NULL && pstk->in_xp[1] != NULL) - pstk->in_xp++; + while (pstk->in_lnk != NULL && + pstk->in_lnk->snext != NULL) + pstk->in_lnk = pstk->in_lnk->snext; } stkpop(); return; @@ -751,11 +752,11 @@ mkstack(NODE *p) break; case NAME: - if (pstk->in_xp) { - for (; pstk->in_xp[0]; pstk->in_xp++) - if (pstk->in_xp[0]->sname == (char *)p->n_sp) + if (pstk->in_lnk) { + for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext) + if (pstk->in_lnk->sname == (char *)p->n_sp) break; - if (pstk->in_xp[0] == NULL) + if (pstk->in_lnk == NULL) uerror("member missing"); } else { uerror("not a struct/union"); @@ -783,7 +784,7 @@ desinit(NODE *p) pstk = pstk->in_prev; /* Empty stack */ if (ISSOU(pstk->in_t)) - pstk->in_xp = pstk->in_sym->ssue->suelem; + pstk->in_lnk = pstk->in_sym->ssue->sylnk; mkstack(p); /* Setup for assignment */ @@ -889,8 +890,8 @@ prtstk(struct instk *in) if (in->in_fl) printf("{ "); printf("soff=%d ", in->in_sym->soffset); if (in->in_t == STRTY) { - if (in->in_xp && in->in_xp[0]) - printf("curel %s ", in->in_xp[0]->sname); + if (in->in_lnk) + printf("curel %s ", in->in_lnk->sname); else printf("END struct"); } diff --git a/usr.bin/pcc/ccom/main.c b/usr.bin/pcc/ccom/main.c index cd3604cc12c..de88379c9e8 100644 --- a/usr.bin/pcc/ccom/main.c +++ b/usr.bin/pcc/ccom/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.4 2007/12/09 18:50:01 ragge Exp $ */ +/* $OpenBSD: main.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2002 Anders Magnusson. All rights reserved. @@ -34,7 +34,7 @@ #include "pass1.h" #include "pass2.h" -int sflag, nflag, oflag, kflag; +int sflag, nflag, oflag, kflag, pflag; int lflag, odebug, rdebug, s2debug, udebug, x2debug; #if !defined(MULTIPASS) || defined(PASST) int iTflag, oTflag; @@ -92,6 +92,10 @@ Wflags(char *str) Wimplicit_int = Wimplicit_function_declaration = 1; return; } + if (strcmp(str, "error") == 0) { + warniserr = 1; + return; + } all = strcmp(str, "W") == 0; for (i = 0; flagstr[i].n; i++) if (all || strcmp(flagstr[i].n, str) == 0) { @@ -112,7 +116,7 @@ main(int argc, char *argv[]) prgname = argv[0]; - while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:kvm:")) != -1) + while ((ch = getopt(argc, argv, "OT:VW:X:Z:gklm:psvwx:")) != -1) switch (ch) { #if !defined(MULTIPASS) || defined(PASS1) case 'X': @@ -202,6 +206,10 @@ main(int argc, char *argv[]) gflag = 1; break; + case 'p': /* Profiling */ + pflag = 1; + break; + case 's': /* Statistics */ ++sflag; break; diff --git a/usr.bin/pcc/ccom/optim.c b/usr.bin/pcc/ccom/optim.c index e4b48144cd5..6ae9991a6c4 100644 --- a/usr.bin/pcc/ccom/optim.c +++ b/usr.bin/pcc/ccom/optim.c @@ -1,4 +1,4 @@ -/* $OpenBSD: optim.c,v 1.2 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: optim.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -43,8 +43,6 @@ # define LO(p) p->n_left->n_op # define LV(p) p->n_left->n_lval -static int nncon(NODE *); - int oflag = 0; /* remove left node */ diff --git a/usr.bin/pcc/ccom/pass1.h b/usr.bin/pcc/ccom/pass1.h index aa9bb3758b9..960e0f40de1 100644 --- a/usr.bin/pcc/ccom/pass1.h +++ b/usr.bin/pcc/ccom/pass1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pass1.h,v 1.8 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: pass1.h,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -90,6 +90,9 @@ extern char *scnames(int); #define SINLINE 00400 #define STNODE 01000 #define SASG 04000 +#define SLOCAL1 010000 +#define SLOCAL2 020000 +#define SLOCAL3 040000 /* alignment of initialized quantities */ #ifndef AL_INIT @@ -116,7 +119,7 @@ union dimfun { */ struct suedef { int suesize; /* Size of the struct */ - struct symtab **suelem;/* points to the list of elements */ + struct symtab *sylnk; /* the list of elements */ int suealign; /* Alignment of this struct */ }; @@ -206,12 +209,6 @@ extern int pragma_packed, pragma_aligned; extern char *pragma_renamed; /* - * Flags used in structures/unions - */ -#define INSTRUCT 02 -#define INUNION 04 - -/* * Flags used in the (elementary) flow analysis ... */ #define FBRK 02 @@ -256,6 +253,7 @@ OFFSZ tsize(TWORD, union dimfun *, struct suedef *), NODE * typenode(NODE *new); void spalloc(NODE *, NODE *, OFFSZ); char *exname(char *); +extern struct rstack *rpole; int oalloc(struct symtab *p, int *poff); void deflabel(char *); @@ -278,6 +276,7 @@ char *addname(char *); char *newstring(char *, int len); void symclear(int level); struct symtab *hide(struct symtab *p); +void soumemb(NODE *, char *, int); int talign(unsigned int, struct suedef *); void bfcode(struct symtab **, int); int chkftn(union arglist *, union arglist *); @@ -305,7 +304,6 @@ void endinit(void); void ilbrace(void); void irbrace(void); void scalinit(NODE *p); -int ftoint(NODE *, CONSZ **); void p1print(char *fmt, ...); char *copst(int); int cdope(int); @@ -321,6 +319,10 @@ int mypragma(char **); void fixdef(struct symtab *); int cqual(TWORD t, TWORD q); void defloc(struct symtab *); +int fldchk(int sz); +int nncon(NODE *); +void cunput(char c); + #ifdef GCC_COMPAT void gcc_init(void); diff --git a/usr.bin/pcc/ccom/pftn.c b/usr.bin/pcc/ccom/pftn.c index f70636f73d7..55d2925688e 100644 --- a/usr.bin/pcc/ccom/pftn.c +++ b/usr.bin/pcc/ccom/pftn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pftn.c,v 1.12 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: pftn.c,v 1.13 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -73,18 +73,16 @@ struct symtab *spname; struct symtab *cftnsp; -static int strunem; /* currently parsed member type */ int arglistcnt, dimfuncnt; /* statistics */ int symtabcnt, suedefcnt; /* statistics */ int autooff, /* the next unused automatic offset */ maxautooff, /* highest used automatic offset in function */ - argoff, /* the next unused argument offset */ - strucoff; /* the next structure offset position */ + argoff; /* the next unused argument offset */ int retlab = NOLAB; /* return label for subroutine */ int brklab; int contlab; int flostat; -int instruct, blevel; +int blevel; int reached, prolab; struct params; @@ -99,12 +97,11 @@ struct params; */ struct rstack { struct rstack *rnext; - int rinstruct; - int rclass; - int rstrucoff; - struct params *rlparam; + int rsou; + int rstr; struct symtab *rsym; -}; + struct symtab *rb; +} *rpole; /* * Linked list for parameter (and struct elements) declaration. @@ -120,6 +117,7 @@ static int nparams; static NODE *arrstk[10]; static int arrstkp; static int intcompare; +static NODE *parlink; void fixtype(NODE *p, int class); int fixclass(int class, TWORD type); @@ -187,14 +185,13 @@ defid(NODE *q, int class) if (blevel == 1) { switch (class) { default: - if (!(class&FIELD)) + if (!(class&FIELD) && !ISFTN(type)) uerror("declared argument %s missing", p->sname ); case MOS: - case STNAME: case MOU: - case UNAME: case TYPEDEF: + case PARAM: ; } } @@ -242,9 +239,7 @@ defid(NODE *q, int class) #endif /* check that redeclarations are to the same structure */ - if ((temp == STRTY || temp == UNIONTY) && - p->ssue != q->n_sue && - class != STNAME && class != UNAME) { + if ((temp == STRTY || temp == UNIONTY) && p->ssue != q->n_sue) { goto mismatch; } @@ -255,15 +250,9 @@ defid(NODE *q, int class) printf(" previous class: %s\n", scnames(scl)); #endif - if (class&FIELD) { - /* redefinition */ - if (!falloc(p, class&FLDSIZ, 1, NIL)) { - /* successful allocation */ - ssave(p); - return; - } - /* blew it: resume at end of switch... */ - } else switch(class) { + if (class & FIELD) + return; + switch(class) { case EXTERN: switch( scl ){ @@ -312,15 +301,7 @@ defid(NODE *q, int class) case MOU: case MOS: - if (scl == class) { - if (oalloc(p, &strucoff)) - break; - if (class == MOU) - strucoff = 0; - ssave(p); - return; - } - break; + return; case EXTDEF: switch (scl) { @@ -333,16 +314,10 @@ defid(NODE *q, int class) } break; - case STNAME: - case UNAME: - if (scl != class) - break; - if (p->ssue->suesize == 0) - return; /* previous entry just a mention */ - break; - case AUTO: case REGISTER: + if (blevel == slev) + goto redec; ; /* mismatch.. */ } @@ -354,12 +329,12 @@ defid(NODE *q, int class) if (blevel == slev || class == EXTERN || class == FORTRAN || class == UFORTRAN) { if (ISSTR(class) && !ISSTR(p->sclass)) { - uerror("redeclaration of %s", p->sname); +redec: uerror("redeclaration of %s", p->sname); return; } } if (blevel == 0) - uerror("redeclaration of %s", p->sname); + goto redec; q->n_sp = p = hide(p); enter: /* make a new entry */ @@ -373,27 +348,9 @@ defid(NODE *q, int class) p->sclass = class; p->slevel = blevel; p->soffset = NOOFFSET; - if (class == STNAME || class == UNAME) { - p->ssue = permalloc(sizeof(struct suedef)); - suedefcnt++; - p->ssue->suesize = 0; - p->ssue->suelem = NULL; - p->ssue->suealign = ALSTRUCT; - } else { - if (q->n_sue == NULL) - cerror("q->n_sue == NULL"); - p->ssue = q->n_sue; -#if 0 - switch (BTYPE(type)) { - case STRTY: - case UNIONTY: - p->ssue = q->n_sue; - break; - default: - p->ssue = MKSUE(BTYPE(type)); - } -#endif - } + if (q->n_sue == NULL) + cerror("q->n_sue == NULL"); + p->ssue = q->n_sue; /* copy dimensions */ p->sdf = q->n_df; @@ -404,7 +361,6 @@ defid(NODE *q, int class) /* allocate offsets */ if (class&FIELD) { (void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */ - ssave(p); } else switch (class) { case REGISTER: @@ -416,6 +372,18 @@ defid(NODE *q, int class) else oalloc(p, &autooff); break; + case PARAM: + if (ISARY(p->stype)) { + /* remove array type on parameters before oalloc */ + p->stype += (PTR-ARY); + p->sdf++; + } + if (arrstkp) + dynalloc(p, &argoff); + else + oalloc(p, &argoff); + break; + case STATIC: case EXTDEF: case EXTERN: @@ -429,10 +397,9 @@ defid(NODE *q, int class) case MOU: case MOS: - oalloc(p, &strucoff); + oalloc(p, &rpole->rstr); if (class == MOU) - strucoff = 0; - ssave(p); + rpole->rstr = 0; break; } @@ -458,13 +425,10 @@ ssave(struct symtab *sym) p->next = NULL; p->sym = sym; - if (lparam == NULL) { - p->prev = (struct params *)&lpole; + if ((p->prev = lparam) == NULL) lpole = p; - } else { + else lparam->next = p; - p->prev = lparam; - } lparam = p; } @@ -476,6 +440,7 @@ ftnend() { extern struct savbc *savbc; extern struct swdef *swpole; + extern int tvaloff; char *c; if (retlab != NOLAB && nerrors == 0) { /* inside a real function */ @@ -484,7 +449,7 @@ ftnend() c = cftnsp->soname; SETOFF(maxautooff, ALCHAR); send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c, - cftnsp->stype, cftnsp->sclass == EXTDEF, retlab); + cftnsp->stype, cftnsp->sclass == EXTDEF, retlab, tvaloff); } tcheck(); @@ -510,6 +475,10 @@ ftnend() tmpfree(); /* Release memory resources */ } +static struct symtab nulsym = { + { NULL, 0, 0, 0, 0 }, "null", "null", INT, 0, NULL, NULL +}; + void dclargs() { @@ -517,15 +486,12 @@ dclargs() union arglist *al, *al2, *alb; struct params *a; struct symtab *p, **parr = NULL; /* XXX gcc */ - char *c; int i; - argoff = ARGINIT; - /* * Deal with fun(void) properly. */ - if (nparams == 1 && lparam->sym->stype == VOID) + if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID) goto done; /* @@ -536,11 +502,13 @@ dclargs() parr = tmpalloc(sizeof(struct symtab *) * nparams); if (nparams) - for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole; - a = a->prev) { - + for (a = lparam, i = 0; a != NULL; a = a->prev) { p = a->sym; parr[i++] = p; + if (p == NULL) { + uerror("parameter %d name missing", i); + p = &nulsym; /* empty symtab */ + } if (p->stype == FARG) { p->stype = INT; p->ssue = MKSUE(INT); @@ -552,8 +520,6 @@ dclargs() werror("function declared as argument"); p->stype = INCREF(p->stype); } - /* always set aside space, even for register arguments */ - oalloc(p, &argoff); #ifdef STABS if (gflag) stabs_newsym(p); @@ -579,59 +545,47 @@ dclargs() if (chkftn(al, alb)) uerror("function doesn't match prototype"); intcompare = 0; + + } + + if (oldstyle && nparams) { + /* Must recalculate offset for oldstyle args here */ + argoff = ARGINIT; + for (i = 0; i < nparams; i++) { + parr[i]->soffset = NOOFFSET; + oalloc(parr[i], &argoff); + } } + done: cendarg(); - c = cftnsp->soname; -#if 0 - prolab = getlab(); - send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype, - cftnsp->sclass == EXTDEF, prolab); -#endif + plabel(prolab); /* after prolog, used in optimization */ retlab = getlab(); bfcode(parr, nparams); plabel(getlab()); /* used when spilling */ + if (parlink) + ecomp(parlink); + parlink = NIL; lparam = NULL; nparams = 0; + symclear(1); /* In case of function pointer args */ } /* - * reference to a structure or union, with no definition + * Struct/union/enum symtab construction. */ -NODE * -rstruct(char *tag, int soru) +static void +defstr(struct symtab *sp, int class) { - struct symtab *p; - NODE *q; - - p = (struct symtab *)lookup(tag, STAGNAME); - switch (p->stype) { - - case UNDEF: - def: - q = block(NAME, NIL, NIL, 0, 0, 0); - q->n_sp = p; - q->n_type = (soru&INSTRUCT) ? STRTY : - ((soru&INUNION) ? UNIONTY : 0); - defid(q, (soru&INSTRUCT) ? STNAME : - ((soru&INUNION) ? UNAME : 0)); - nfree(q); - break; - - case STRTY: - if (soru & INSTRUCT) - break; - goto def; - - case UNIONTY: - if (soru & INUNION) - break; - goto def; - - } - q = mkty(p->stype, 0, p->ssue); - q->n_sue = p->ssue; - return q; + sp->ssue = permalloc(sizeof(struct suedef)); + sp->ssue->suesize = 0; + sp->ssue->sylnk = NULL; + sp->ssue->suealign = 0; + sp->sclass = class; + if (class == STNAME) + sp->stype = STRTY; + else if (class == UNAME) + sp->stype = UNIONTY; } /* @@ -643,23 +597,26 @@ deftag(char *name, int class) { struct symtab *sp; - sp = lookup(name, STAGNAME); - if (sp->ssue == NULL) - sp->ssue = permalloc(sizeof(struct suedef)); - if (sp->sclass == SNULL) { + if ((sp = lookup(name, STAGNAME))->ssue == NULL) { /* New tag */ - sp->sclass = class; - } else if (sp->slevel < blevel) { - /* declared at different block level, hide it */ - sp = hide(sp); - sp->sclass = class; - } else if (sp->sclass != class) { - /* redeclaration of tag */ + defstr(sp, class); + } else if (sp->sclass != class) uerror("tag %s redeclared", name); - } return sp; } +/* + * reference to a structure or union, with no definition + */ +NODE * +rstruct(char *tag, int soru) +{ + struct symtab *sp; + + sp = deftag(tag, soru); + return mkty(sp->stype, 0, sp->ssue); +} + static int enumlow, enumhigh; int enummer; @@ -701,8 +658,12 @@ enumhd(char *name) return NULL; sp = deftag(name, ENAME); - if (sp->stype != UNDEF) /* enum type already declared */ - uerror("%s redeclared", name); + if (sp->stype != UNDEF) { + if (sp->slevel == blevel) + uerror("%s redeclared", name); + sp = hide(sp); + defstr(sp, ENAME); + } return sp; } @@ -759,39 +720,28 @@ struct rstack * bstruct(char *name, int soru) { struct rstack *r; - struct symtab *s; - NODE *q; + struct symtab *sp; - if (name != NULL) - s = lookup(name, STAGNAME); - else - s = NULL; + if (name != NULL) { + sp = deftag(name, soru); + if (sp->ssue->suealign != 0) { + if (sp->slevel < blevel) { + sp = hide(sp); + defstr(sp, soru); + } else + uerror("%s redeclared", name); + } + sp->ssue->suealign = ALSTRUCT; + } else + sp = NULL; r = tmpalloc(sizeof(struct rstack)); - r->rinstruct = instruct; - r->rclass = strunem; - r->rstrucoff = strucoff; - - strucoff = 0; - instruct = soru; - q = block(NAME, NIL, NIL, 0, 0, 0); - q->n_sp = s; - if (instruct==INSTRUCT) { - strunem = MOS; - q->n_type = STRTY; - if (s != NULL) - defid(q, STNAME); - } else if(instruct == INUNION) { - strunem = MOU; - q->n_type = UNIONTY; - if (s != NULL) - defid(q, UNAME); - } else { - cerror("bstruct"); - } - r->rsym = q->n_sp; - r->rlparam = lparam; - nfree(q); + r->rsou = soru; + r->rstr = 0; + r->rsym = sp; + r->rb = NULL; + r->rnext = rpole; + rpole = r; return r; } @@ -803,12 +753,10 @@ NODE * dclstruct(struct rstack *r) { NODE *n; - struct params *l, *m; struct suedef *sue; - struct symtab *p; + struct symtab *sp; int al, sa, sz, coff; TWORD temp; - int i, high, low; if (r->rsym == NULL) { sue = permalloc(sizeof(struct suedef)); @@ -817,65 +765,49 @@ dclstruct(struct rstack *r) sue->suealign = ALSTRUCT; } else sue = r->rsym->ssue; + if (sue->suealign == 0) /* suealign == 0 is undeclared struct */ + sue->suealign = ALSTRUCT; #ifdef PCC_DEBUG if (ddebug) printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??"); #endif - temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:0); - instruct = r->rinstruct; - strunem = r->rclass; + temp = r->rsou == STNAME ? STRTY : UNIONTY; al = ALSTRUCT; - high = low = 0; - - if ((l = r->rlparam) == NULL) - l = lpole; - else - l = l->next; - - /* memory for the element array must be allocated first */ - for (m = l, i = 1; m != NULL; m = m->next) - i++; - sue->suelem = permalloc(sizeof(struct symtab *) * i); - coff = 0; if (pragma_packed || pragma_aligned) - strucoff = 0; /* must recount it */ - - for (i = 0; l != NULL; l = l->next) { - sue->suelem[i++] = p = l->sym; + rpole->rstr = 0; /* must recount it */ - if (p == NULL) - cerror("gummy structure member"); - sa = talign(p->stype, p->ssue); - if (p->sclass & FIELD) - sz = p->sclass&FLDSIZ; + sue->sylnk = r->rb; + for (sp = r->rb; sp; sp = sp->snext) { + sa = talign(sp->stype, sp->ssue); + if (sp->sclass & FIELD) + sz = sp->sclass&FLDSIZ; else - sz = tsize(p->stype, p->sdf, p->ssue); + sz = tsize(sp->stype, sp->sdf, sp->ssue); if (pragma_packed || pragma_aligned) { /* XXX check pack/align sizes */ - p->soffset = coff; + sp->soffset = coff; if (pragma_aligned) coff += ALLDOUBLE; else coff += sz; - strucoff = coff; + rpole->rstr = coff; } - if (sz > strucoff) - strucoff = sz; /* for use with unions */ + if (sz > rpole->rstr) + rpole->rstr = sz; /* for use with unions */ /* * set al, the alignment, to the lcm of the alignments * of the members. */ SETOFF(al, sa); } - sue->suelem[i] = NULL; - SETOFF(strucoff, al); + SETOFF(rpole->rstr, al); - sue->suesize = strucoff; + sue->suesize = rpole->rstr; sue->suealign = al; pragma_packed = pragma_aligned = 0; @@ -887,25 +819,47 @@ dclstruct(struct rstack *r) #ifdef PCC_DEBUG if (ddebug>1) { - int i; - - printf("\tsize %d align %d elem %p\n", - sue->suesize, sue->suealign, sue->suelem); - for (i = 0; sue->suelem[i] != NULL; ++i) { - printf("\tmember %s(%p)\n", - sue->suelem[i]->sname, sue->suelem[i]); + printf("\tsize %d align %d link %p\n", + sue->suesize, sue->suealign, sue->sylnk); + for (sp = sue->sylnk; sp != NULL; sp = sp->snext) { + printf("\tmember %s(%p)\n", sp->sname, sp); } } #endif - strucoff = r->rstrucoff; - if ((lparam = r->rlparam) != NULL) - lparam->next = NULL; + rpole = r->rnext; n = mkty(temp, 0, sue); return n; } /* + * Add a new member to the current struct or union being declared. + */ +void +soumemb(NODE *n, char *name, int class) +{ + struct symtab *sp, *lsp; + + if (rpole == NULL) + cerror("soumemb"); + + lsp = NULL; + for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext) + if (sp->sname == name) + uerror("redeclaration of %s", name); + + sp = getsymtab(name, SMOSNAME); + if (rpole->rb == NULL) + rpole->rb = sp; + else + lsp->snext = sp; + n->n_sp = sp; + defid(n, class); +} + + + +/* * error printing routine in parser */ void yyerror(char *s); @@ -930,74 +884,44 @@ void ftnarg(NODE *p) { NODE *q; - struct symtab *s; #ifdef PCC_DEBUG if (ddebug > 2) printf("ftnarg(%p)\n", p); #endif /* - * Enter argument onto param stack. - * Do not declare parameters until later (in dclargs); - * the function must be declared first. - * put it on the param stack in reverse order, due to the - * nature of the stack it will be reclaimed correct. + * Push argument symtab entries onto param stack in reverse order, + * due to the nature of the stack it will be reclaimed correct. */ for (; p->n_op != NAME; p = p->n_left) { - if (p->n_op == (UCALL) && p->n_left->n_op == NAME) + if (p->n_op == UCALL && p->n_left->n_op == NAME) return; /* Nothing to enter */ if (p->n_op == CALL && p->n_left->n_op == NAME) break; } p = p->n_right; - blevel = 1; - while (p->n_op == CM) { q = p->n_right; if (q->n_op != ELLIPSIS) { - s = lookup((char *)q->n_sp, 0); - if (s->stype != UNDEF) { - if (s->slevel > 0) - uerror("parameter '%s' redefined", - s->sname); - s = hide(s); - } - s->soffset = NOOFFSET; - s->sclass = PARAM; - s->stype = q->n_type; - s->sdf = q->n_df; - s->ssue = q->n_sue; - ssave(s); + ssave(q->n_sp); nparams++; #ifdef PCC_DEBUG if (ddebug > 2) printf(" saving sym %s (%p) from (%p)\n", - s->sname, s, q); + q->n_sp->sname, q->n_sp, q); #endif } p = p->n_left; } - s = lookup((char *)p->n_sp, 0); - if (s->stype != UNDEF) { - if (s->slevel > 0) - uerror("parameter '%s' redefined", s->sname); - s = hide(s); - } - s->soffset = NOOFFSET; - s->sclass = PARAM; - s->stype = p->n_type; - s->sdf = p->n_df; - s->ssue = p->n_sue; - ssave(s); + ssave(p->n_sp); if (p->n_type != VOID) nparams++; - blevel = 0; #ifdef PCC_DEBUG if (ddebug > 2) printf(" saving sym %s (%p) from (%p)\n", - s->sname, s, p); + nparams ? p->n_sp->sname : "<noname>", p->n_sp, p); #endif } @@ -1103,7 +1027,7 @@ tsize(TWORD ty, union dimfun *d, struct suedef *sue) return(SZINT); } } else { - if (sue->suelem == NULL) + if (sue->suealign == 0) uerror("unknown structure/union/enum"); } @@ -1221,7 +1145,7 @@ oalloc(struct symtab *p, int *poff ) } else #endif if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR || - p->stype == SHORT || p->stype == USHORT)) { + p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) { off = upoff(SZINT, ALINT, &noff); #ifndef RTOLBYTES off = noff - tsz; @@ -1243,7 +1167,24 @@ oalloc(struct symtab *p, int *poff ) } /* - * Allocate space on the stack for dynamic arrays. + * Delay emission of code generated in argument headers. + */ +static void +edelay(NODE *p) +{ + if (blevel == 1) { + /* Delay until after declarations */ + if (parlink == NULL) + parlink = p; + else + parlink = block(COMOP, parlink, p, 0, 0, 0); + } else + ecomp(p); +} + +/* + * Allocate space on the stack for dynamic arrays (or at least keep track + * of the index). * Strategy is as follows: * - first entry is a pointer to the dynamic datatype. * - if it's a one-dimensional array this will be the only entry used. @@ -1258,41 +1199,66 @@ dynalloc(struct symtab *p, int *poff) union dimfun *df; NODE *n, *nn, *tn, *pol; TWORD t; - int i, no; + int astkp, no; /* - * The pointer to the array is stored in a TEMP node, which number - * is in the soffset field; + * The pointer to the array is not necessarily stored in a + * TEMP node, but if it is, its number is in the soffset field; */ t = p->stype; - p->sflags |= (STNODE|SDYNARRAY); - p->stype = INCREF(p->stype); /* Make this an indirect pointer */ - tn = tempnode(0, p->stype, p->sdf, p->ssue); - p->soffset = regno(tn); + astkp = 0; + if (ISARY(t) && blevel == 1) { + /* must take care of side effects of dynamic arg arrays */ + if (p->sdf->ddim < 0) { + /* first-level array will be indexed correct */ + edelay(arrstk[astkp++]); + } + p->sdf++; + p->stype += (PTR-ARY); + t = p->stype; + } + if (ISARY(t)) { + p->sflags |= (STNODE|SDYNARRAY); + p->stype = INCREF(p->stype); /* Make this an indirect pointer */ + tn = tempnode(0, p->stype, p->sdf, p->ssue); + p->soffset = regno(tn); + } else { + oalloc(p, poff); + tn = NIL; + } df = p->sdf; pol = NIL; - for (i = 0; ISARY(t); t = DECREF(t), df++) { - if (df->ddim >= 0) + for (; t > BTMASK; t = DECREF(t)) { + if (!ISARY(t)) continue; - n = arrstk[i++]; - nn = tempnode(0, INT, 0, MKSUE(INT)); - no = regno(nn); - ecomp(buildtree(ASSIGN, nn, n)); /* Save size */ + if (df->ddim < 0) { + n = arrstk[astkp++]; + nn = tempnode(0, INT, 0, MKSUE(INT)); + no = regno(nn); + edelay(buildtree(ASSIGN, nn, n)); + + df->ddim = -no; + n = tempnode(no, INT, 0, MKSUE(INT)); + } else + n = bcon(df->ddim); - df->ddim = -no; - n = tempnode(no, INT, 0, MKSUE(INT)); - if (pol == NIL) - pol = n; - else - pol = buildtree(MUL, pol, n); + pol = (pol == NIL ? n : buildtree(MUL, pol, n)); + df++; } /* Create stack gap */ - if (pol == NIL) - uerror("aggregate dynamic array not allowed"); - else - spalloc(tn, pol, tsize(t, 0, p->ssue)); + if (blevel == 1) { + if (tn) + tfree(tn); + if (pol) + tfree(pol); + } else { + if (pol == NIL) + uerror("aggregate dynamic array not allowed"); + if (tn) + spalloc(tn, pol, tsize(t, 0, p->ssue)); + } arrstkp = 0; } @@ -1343,24 +1309,24 @@ falloc(struct symtab *p, int w, int new, NODE *pty) } if( w == 0 ){ /* align only */ - SETOFF( strucoff, al ); + SETOFF( rpole->rstr, al ); if( new >= 0 ) uerror( "zero size field"); return(0); } - if( strucoff%al + w > sz ) SETOFF( strucoff, al ); + if( rpole->rstr%al + w > sz ) SETOFF( rpole->rstr, al ); if( new < 0 ) { - strucoff += w; /* we know it will fit */ + rpole->rstr += w; /* we know it will fit */ return(0); } /* establish the field */ if( new == 1 ) { /* previous definition */ - if( p->soffset != strucoff || p->sclass != (FIELD|w) ) return(1); + if( p->soffset != rpole->rstr || p->sclass != (FIELD|w) ) return(1); } - p->soffset = strucoff; - strucoff += w; + p->soffset = rpole->rstr; + rpole->rstr += w; p->stype = type; fldty( p ); return(0); @@ -1382,7 +1348,7 @@ nidcl(NODE *p, int class) if (class == SNULL) { if (blevel > 1) class = AUTO; - else if (blevel != 0 || instruct) + else if (blevel != 0 || rpole) cerror( "nidcl error" ); else /* blevel = 0 */ commflag = 1, class = EXTERN; @@ -1498,8 +1464,8 @@ typenode(NODE *p) type = class = qual = sig = uns = 0; saved = NIL; - if (strunem != 0) - class = strunem; + if (rpole != NULL) + class = rpole->rsou == STNAME ? MOS : MOU; for (q = p; p; p = p->n_left) { switch (p->n_op) { @@ -2376,7 +2342,7 @@ fixtype(NODE *p, int class) } /* detect function arguments, watching out for structure declarations */ - if (instruct && ISFTN(type)) { + if (rpole && ISFTN(type)) { uerror("function illegal in structure or union"); type = INCREF(type); } @@ -2404,10 +2370,8 @@ fixclass(int class, TWORD type) { /* first, fix null class */ if (class == SNULL) { - if (instruct&INSTRUCT) - class = MOS; - else if (instruct&INUNION) - class = MOU; + if (rpole) + class = rpole->rsou == STNAME ? MOS : MOU; else if (blevel == 0) class = EXTDEF; else @@ -2433,24 +2397,23 @@ fixclass(int class, TWORD type) } } - if( class&FIELD ){ - if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" ); - return( class ); - } - - switch( class ){ + if (class & FIELD) { + if (rpole && rpole->rsou != STNAME) + uerror("illegal use of field"); + return(class); + } - case MOU: - if( !(instruct&INUNION) ) uerror( "illegal MOU class" ); - return( class ); + switch (class) { case MOS: - if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" ); - return( class ); + case MOU: + if (rpole == NULL) + uerror("illegal member class"); + return(class); case REGISTER: if (blevel == 0) - uerror( "illegal register declaration" ); + uerror("illegal register declaration"); if (blevel == 1) return(PARAM); else @@ -2472,13 +2435,12 @@ fixclass(int class, TWORD type) uerror( "fortran function has wrong type" ); } } - case STNAME: - case UNAME: case EXTERN: case STATIC: case EXTDEF: case TYPEDEF: case USTATIC: + case PARAM: return( class ); default: @@ -2543,6 +2505,18 @@ getsymtab(char *name, int flags) return s; } +int +fldchk(int sz) +{ + if (rpole->rsou != STNAME) + uerror("field outside of structure"); + if (sz < 0 || sz >= FIELD) { + uerror("illegal field size"); + return 1; + } + return 0; +} + #ifdef PCC_DEBUG static char * ccnames[] = { /* names of storage classes */ diff --git a/usr.bin/pcc/ccom/scan.l b/usr.bin/pcc/ccom/scan.l index 4e349815a0f..32dd7857a7e 100644 --- a/usr.bin/pcc/ccom/scan.l +++ b/usr.bin/pcc/ccom/scan.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scan.l,v 1.4 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: scan.l,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2002 Anders Magnusson. All rights reserved. @@ -58,7 +58,7 @@ int notype, parbal; #define CPP_HASH 4 #ifdef STABS -#define STABS_LINE(x) if (gflag && blevel) stabs_line(x) +#define STABS_LINE(x) if (gflag && blevel > 1) stabs_line(x) #else #define STABS_LINE(x) #endif @@ -125,10 +125,10 @@ extern void yyset_lineno (int); notype=1; return(C_TYPE); } "sizeof" { return(C_SIZEOF); } "static" { yylval.intval = STATIC; return(C_CLASS); } -"struct" { yylval.intval = INSTRUCT; notype=1; return(C_STRUCT); } +"struct" { yylval.intval = STNAME; notype=1; return(C_STRUCT); } "switch" { return(C_SWITCH); } "typedef" { yylval.intval = TYPEDEF; return(C_CLASS); } -"union" { yylval.intval = INUNION; notype=1; return(C_STRUCT); } +"union" { yylval.intval = UNAME; notype=1; return(C_STRUCT); } "unsigned" { yylval.nodep = mkty((TWORD)UNSIGNED, 0, MKSUE(UNSIGNED)); notype=1; return(C_TYPE); } "void" { yylval.nodep = mkty((TWORD)VOID, 0, MKSUE(VOID)); @@ -138,22 +138,22 @@ extern void yyset_lineno (int); return(C_QUALIFIER); } "while" { return(C_WHILE); } -{L}({L}|{D})* { struct symtab *s; - int i; +{L}({L}|{D})* { struct symtab *s; + int i = 0; - yylval.strp = addname(yytext); + yylval.strp = addname(yytext); #ifdef GCC_COMPAT - if ((i = gcc_keyword(yylval.strp, - &yylval.nodep)) != 0) - return i; + if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0) + return i; #endif - if (!notype) { - s = lookup(yylval.strp, SNOCREAT); - if (s && s->sclass == TYPEDEF) - return notype=1, C_TYPENAME; - } - return(C_NAME); + if (i == 0) { + if (notype) + return(C_NAME); + s = lookup(yylval.strp, SNOCREAT); + return s && s->sclass == TYPEDEF ? + notype=1, C_TYPENAME : C_NAME; } + } 0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); } 0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); } @@ -204,7 +204,7 @@ L?\"(\\.|[^\\"])*\" { "!=" { yylval.intval = NE; return(C_EQUOP); } ";" { notype = 0; return(';'); } ("{"|"<%") { notype = 0; return('{'); } -("}"|"%>") { return('}'); } +("}"|"%>") { if (rpole) notype = 1; return('}'); } "," { if (parbal) notype = 0; return(','); } ":" { return(':'); } "=" { return('='); } @@ -446,6 +446,8 @@ control(int t) lineno = val - 1; while (*wr && *wr != '\"') wr++; + if (*wr == 0) + return; if (*wr++ != '\"') goto bad; eptr = wr; @@ -510,3 +512,9 @@ pragma() else bad: werror("unknown pragma"); } + +void +cunput(char c) +{ + unput(c); +} diff --git a/usr.bin/pcc/ccom/stabs.c b/usr.bin/pcc/ccom/stabs.c index 8fe84a5b035..78765545eff 100644 --- a/usr.bin/pcc/ccom/stabs.c +++ b/usr.bin/pcc/ccom/stabs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: stabs.c,v 1.6 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: stabs.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -121,7 +121,7 @@ stabs_init() ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0); ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0); st = ADDTYPE(VOID); - cprint(savestabs, ".stabs \"void:t%d=r%d\",%d,0,0,0\n", + cprint(savestabs, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n", st->num, st->num, N_LSYM); } @@ -132,7 +132,7 @@ stabs_init() void ptype(char *name, int num, int inhnum, long long min, long long max) { - cprint(savestabs, ".stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0", + cprint(savestabs, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n", name, num, inhnum, min, max, N_LSYM); } @@ -196,11 +196,11 @@ void stabs_line(int line) { #ifdef STAB_LINE_ABSOLUTE - cprint(savestabs, ".stabn %d,0,%d," STABLBL, N_SLINE, line, stablbl); + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n", N_SLINE, line, stablbl); #else - cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, exname(curfun)); + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n", N_SLINE, line, stablbl, exname(curfun)); #endif - cprint(1, STABLBL ":", stablbl++); + cprint(1, STABLBL ":\n", stablbl++); } /* @@ -210,12 +210,12 @@ void stabs_lbrac(int blklvl) { #ifdef STAB_LINE_ABSOLUTE - cprint(savestabs, ".stabn %d,0,%d," STABLBL, N_LBRAC, blklvl, stablbl); + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n", N_LBRAC, blklvl, stablbl); #else - cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n", N_LBRAC, blklvl, stablbl, exname(curfun)); #endif - cprint(1, STABLBL ":", stablbl++); + cprint(1, STABLBL ":\n", stablbl++); } /* @@ -225,13 +225,13 @@ void stabs_rbrac(int blklvl) { #ifdef STAB_LINE_ABSOLUTE - cprint(savestabs, ".stabn %d,0,%d," STABLBL "\n", + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "\n", N_RBRAC, blklvl, stablbl); #else - cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n", + cprint(savestabs, "\t.stabn %d,0,%d," STABLBL "-%s\n", N_RBRAC, blklvl, stablbl, exname(curfun)); #endif - cprint(1, STABLBL ":", stablbl++); + cprint(1, STABLBL ":\n", stablbl++); } /* @@ -244,9 +244,9 @@ stabs_file(char *fname) if (mainfile == NULL) mainfile = fname; /* first call */ - cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL, + cprint(savestabs, "\t.stabs \"%s\",%d,0,0," STABLBL "\n", fname, fname == mainfile ? N_SO : N_SOL, stablbl); - cprint(savestabs, STABLBL ":", stablbl++); + cprint(savestabs, STABLBL ":\n", stablbl++); } /* @@ -259,7 +259,7 @@ stabs_func(struct symtab *s) curfun = s->soname; printtype(s, str, sizeof(str)); - cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s", + cprint(savestabs, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n", curfun, s->sclass == STATIC ? 'f' : 'F', str, N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun)); } @@ -330,32 +330,32 @@ stabs_newsym(struct symtab *s) printtype(s, ostr, sizeof(ostr)); switch (s->sclass) { case PARAM: - cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr, + cprint(savestabs, "\t.stabs \"%s:p%s\",%d,0,%d,%d\n", sname, ostr, N_PSYM, suesize, BIT2BYTE(s->soffset)); break; case AUTO: - cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr, + cprint(savestabs, "\t.stabs \"%s:%s\",%d,0,%d,%d\n", sname, ostr, N_LSYM, suesize, BIT2BYTE(s->soffset)); break; case STATIC: if (blevel) - cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr, + cprint(savestabs, "\t.stabs \"%s:V%s\",%d,0,%d," LABFMT "\n", sname, ostr, N_LCSYM, suesize, s->soffset); else - cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr, + cprint(savestabs, "\t.stabs \"%s:S%s\",%d,0,%d,%s\n", sname, ostr, N_LCSYM, suesize, exname(sname)); break; case EXTERN: case EXTDEF: - cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr, + cprint(savestabs, "\t.stabs \"%s:G%s\",%d,0,%d,0\n", sname, ostr, N_GSYM, suesize); break; case REGISTER: - cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr, + cprint(savestabs, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", sname, ostr, N_RSYM, 1, s->soffset); break; @@ -377,9 +377,15 @@ stabs_struct(struct symtab *p, struct suedef *sue) { } +static struct foo { + struct foo *next; + char *str; +} *foopole; + void cprint(int p2, char *fmt, ...) { + extern int inftn; va_list ap; char *str; @@ -387,12 +393,19 @@ cprint(int p2, char *fmt, ...) if (p2) { str = tmpvsprintf(fmt, ap); str = newstring(str, strlen(str)); /* XXX - for inlines */ - send_passt(IP_ASM, str); - } else { - putchar('\t'); + if (inftn == 0) { + struct foo *w = tmpalloc(sizeof(struct foo)); + w->str = str; + w->next = foopole; + foopole = w; + } else { + while (foopole) + send_passt(IP_ASM, foopole->str), + foopole = foopole->next; + send_passt(IP_ASM, str); + } + } else vprintf(fmt, ap); - putchar('\n'); - } va_end(ap); } diff --git a/usr.bin/pcc/ccom/trees.c b/usr.bin/pcc/ccom/trees.c index 70fa2caefe6..e7bd9a87f8a 100644 --- a/usr.bin/pcc/ccom/trees.c +++ b/usr.bin/pcc/ccom/trees.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trees.c,v 1.13 2008/01/12 17:26:16 ragge Exp $ */ +/* $OpenBSD: trees.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -76,6 +76,7 @@ static int opact(NODE *p); static int moditype(TWORD); static NODE *strargs(NODE *); static void rmcops(NODE *p); +int inftn; /* currently between epilog/prolog */ /* some special actions, used in finding the type of nodes */ # define NCVT 01 @@ -115,7 +116,6 @@ buildtree(int o, NODE *l, NODE *r) struct symtab *sp = NULL; /* XXX gcc */ NODE *lr, *ll; char *name; - struct symtab **elem; #ifdef PCC_DEBUG if (bdebug) { @@ -245,6 +245,8 @@ runtime: if (actions & LVAL) { /* check left descendent */ if (notlval(p->n_left)) { uerror("lvalue required"); + nfree(p); + return l; #ifdef notyet } else { if ((l->n_type > BTMASK && ISCON(l->n_qual)) || @@ -350,16 +352,15 @@ runtime: break; } - if ((elem = l->n_sue->suelem) == NULL) + if ((sp = l->n_sue->sylnk) == NULL) uerror("undefined struct or union"); name = r->n_name; - for (; *elem != NULL; elem++) { - sp = *elem; + for (; sp != NULL; sp = sp->snext) { if (sp->sname == name) break; } - if (*elem == NULL) + if (sp == NULL) uerror("member '%s' not declared", name); r->n_sp = sp; @@ -1591,6 +1592,8 @@ eprint(NODE *p, int down, int *a, int *b) ty = coptype( p->n_op ); printf("%p) %s, ", p, copst(p->n_op)); + if (p->n_op == XARG || p->n_op == XASM) + printf("id '%s', ", p->n_name); if (ty == LTYPE) { printf(CONFMT, p->n_lval); printf(", %d, ", (p->n_op != NAME && p->n_op != ICON) ? @@ -2058,6 +2061,10 @@ p2tree(NODE *p) printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue)); break; + case XARG: + case XASM: + break; + default: printf( "\n" ); } @@ -2125,6 +2132,10 @@ p2tree(NODE *p) p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR; break; + case XARG: + case XASM: + break; + default: p->n_name = ""; } @@ -2220,6 +2231,7 @@ send_passt(int type, ...) defloc(cftnsp); /* FALLTHROUGH */ case IP_PROLOG: + inftn = type == IP_PROLOG ? 1 : 0; ipp = (struct interpass_prolog *)ip; ipp->ipp_regs = va_arg(ap, int); ipp->ipp_autos = va_arg(ap, int); @@ -2227,7 +2239,7 @@ send_passt(int type, ...) ipp->ipp_type = va_arg(ap, TWORD); ipp->ipp_vis = va_arg(ap, int); ip->ip_lbl = va_arg(ap, int); - ipp->ip_tmpnum = tvaloff; + ipp->ip_tmpnum = va_arg(ap, int); ipp->ip_lblnum = crslab; if (type == IP_PROLOG) ipp->ip_lblnum--; diff --git a/usr.bin/pcc/config.h b/usr.bin/pcc/config.h index 11eb06e5e4f..47f4ced9ead 100644 --- a/usr.bin/pcc/config.h +++ b/usr.bin/pcc/config.h @@ -1,8 +1,8 @@ -/* $OpenBSD: config.h,v 1.4 2007/10/07 19:26:26 otto Exp $ */ +/* $OpenBSD: config.h,v 1.5 2008/04/11 20:45:51 stefan Exp $ */ #define PCC_MAJOR 0 #define PCC_MINOR 9 -#define PCC_MINORMINOR 8 -#define VERSSTR "pcc 0.9.8" +#define PCC_MINORMINOR 9 +#define VERSSTR "pcc 0.9.9" #define YYTEXT_POINTER 1 diff --git a/usr.bin/pcc/cpp/cpp.1 b/usr.bin/pcc/cpp/cpp.1 index 2f4606ee011..50a7a9bc81c 100644 --- a/usr.bin/pcc/cpp/cpp.1 +++ b/usr.bin/pcc/cpp/cpp.1 @@ -1,24 +1,24 @@ -.\" $Id: cpp.1,v 1.3 2008/01/12 17:58:29 ragge Exp $ +.\" $Id: cpp.1,v 1.4 2008/04/11 20:45:52 stefan Exp $ .\" $NetBSD$ -.\" $OpenBSD: cpp.1,v 1.3 2008/01/12 17:58:29 ragge Exp $ +.\" $OpenBSD: cpp.1,v 1.4 2008/04/11 20:45:52 stefan Exp $ ."\ .\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net> -.\" -.\" Permission to use, copy, modify, and/or distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM -.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND -.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF .\" THIS SOFTWARE. .\" .Dd September 17, 2007 -.Dt cpp 1 +.Dt CPP 1 .Os .Sh NAME .Nm cpp @@ -34,7 +34,6 @@ .Op Fl U Ar macro .Op Ar infile | - .Op Ar outfile -.Pp .Sh DESCRIPTION The .Nm @@ -45,7 +44,7 @@ It is used to include header files, expand macro definitions, and perform conditional compilation. .Pp -The +The .Ar infile input file is optional. If not provided or the file name is @@ -65,6 +64,9 @@ It writes by default to standard output. .\" The options are as follows: .Bl -tag -width Ds +.It Fl ? +Show command line usage for +.Nm . .It Fl C Do not discard comments. .It Fl D Ar macro[=value] @@ -73,14 +75,14 @@ Fake a definition at the beginning by using .Ar macro=value Dc . If .Ar value -is not set on command-line, then defines as 1. +is not set on command-line, then define it as 1. .\" TODO: show example .It Fl dM Print list of .Dq #define statements to standard output for all defined macros other than builtin macros (see below). -The normal results of preprocessing are not outputted. +The normal results of preprocessing are not output. .\" TODO this doesn't show predefined macros .\" other -d options are ignored .It Fl I Ar path @@ -106,8 +108,9 @@ Generate dependencies for Add .Ar path to the list of system directories containing needed header files. +The .Fl S -may be specified multiple times. +option may be specified multiple times. Note: .Nm does not have a default include directory defined. @@ -120,25 +123,22 @@ Do not define the .Dv __DATE__ , .Dv __STDC__ , and -.Dv __STDC_VERSION__ , +.Dv __STDC_VERSION__ macros. .\" .It Fl U Ar macro Undefine a macro at the beginning by using .Do #undef .Ar macro Dc . -.It Fl v -Display version. .It Fl V Verbose debugging output. .Fl V can be repeated for further details. .\" -V only available if cpp source built with CPP_DEBUG, which is the default. -.It Fl ? -Show command line usage for -.Nm . +.It Fl v +Display version. .El -.Sh Builtin Macros +.Ss Builtin Macros A few macros are interpreted inside the .Nm cpp program: @@ -151,19 +151,22 @@ in quotes. .It __FILE__ Expands to the name of the current input file in quotes. When read from standard input, it expands to -.Qq Ao stdin Ac . +.Qq Aq stdin . .It __LINE__ Expands to the line number of the current line containing the macro. .It __STDC__ Expands to the constant 1. -This means the compiler conforms to ISO Standard C, -ISO/IEC 9899:1990 +This means the compiler conforms to +.St -isoC .Po also known as .Do C90 Dc Pc . .It __STDC_VERSION__ Expands to .Dq 199901L -which indicates it supports ISO/IEC 9899:1999 standard +which indicates that +.Nm +supports +.St -isoC-99 .Po commonly referred to as .Do C99 Dc Pc . .It __TIME__ @@ -193,8 +196,8 @@ An error occurred. .Sh HISTORY The .Nm -command comes from the original Portable C Compiler by S. C. -Johnson, written in the late 70's. +command comes from the original Portable C Compiler by S. C. Johnson, +written in the late 70's. The code originates from the V6 preprocessor with some additions from V7 cpp and ansi/c99 support. .Pp diff --git a/usr.bin/pcc/cpp/cpp.c b/usr.bin/pcc/cpp/cpp.c index b2f9702f35a..095b75da475 100644 --- a/usr.bin/pcc/cpp/cpp.c +++ b/usr.bin/pcc/cpp/cpp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpp.c,v 1.8 2008/01/12 17:58:29 ragge Exp $ */ +/* $OpenBSD: cpp.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). @@ -101,7 +101,7 @@ int dflag; /* debug printouts */ int ofd; usch outbuf[CPPBUF]; -int obufp, istty; +int obufp, istty, inmac; int Cflag, Mflag, dMflag; usch *Mfile; struct initar *initar; @@ -983,7 +983,8 @@ expmac(struct recur *rp) else orgexp++; - DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp)); + DDPRINT(("id1: typ %d noexp %d orgexp %d\n", + c, noexp, orgexp)); if (c == IDENT) { /* XXX numbers? */ DDPRINT(("id2: str %s\n", yytext)); /* OK to always expand here? */ @@ -1118,12 +1119,19 @@ expdef(vp, rp, gotwarn) * read arguments and store them on heap. * will be removed just before return from this function. */ + inmac = 1; sptr = stringbuf; + instr = 0; for (i = 0; i < narg && c != ')'; i++) { args[i] = stringbuf; plev = 0; while ((c = yylex()) == WSPACE || c == '\n') ; + DDPRINT((":AAA (%d)", c)); + if (instr == -1) + savch(NOEXP), instr = 1; + if (c == NOEXP) + instr = 1; for (;;) { if (plev == 0 && (c == ')' || c == ',')) break; @@ -1134,10 +1142,14 @@ expdef(vp, rp, gotwarn) savstr((usch *)yytext); while ((c = yylex()) == '\n') savch('\n'); + if (c == EXPAND) + instr = 0; } while (args[i] < stringbuf && (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) stringbuf--; + if (instr == 1) + savch(EXPAND), instr = -1; savch('\0'); } if (ellips) @@ -1145,8 +1157,12 @@ expdef(vp, rp, gotwarn) if (ellips && c != ')') { args[i] = stringbuf; plev = 0; + instr = 0; while ((c = yylex()) == WSPACE) ; + if (c == NOEXP) + instr++; + DDPRINT((":AAY (%d)", c)); for (;;) { if (plev == 0 && c == ')') break; @@ -1154,9 +1170,16 @@ expdef(vp, rp, gotwarn) plev++; if (c == ')') plev--; - savstr((usch *)yytext); + if (plev == 0 && c == ',' && instr) { + savch(EXPAND); + savch(','); + savch(NOEXP); + } else + savstr((usch *)yytext); while ((c = yylex()) == '\n') savch('\n'); + if (c == EXPAND) + instr--; } while (args[i] < stringbuf && (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) @@ -1171,6 +1194,7 @@ expdef(vp, rp, gotwarn) if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) error("wrong arg count"); + inmac = 0; while (gotwarn--) cunput(WARN); diff --git a/usr.bin/pcc/cpp/scanner.l b/usr.bin/pcc/cpp/scanner.l index 5e155d30d52..e5dca5e9f26 100644 --- a/usr.bin/pcc/cpp/scanner.l +++ b/usr.bin/pcc/cpp/scanner.l @@ -1,5 +1,5 @@ %{ -/* $OpenBSD: scanner.l,v 1.8 2008/01/12 17:58:29 ragge Exp $ */ +/* $OpenBSD: scanner.l,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2004 Anders Magnusson. All rights reserved. @@ -32,6 +32,7 @@ #include <ctype.h> #include <unistd.h> #include <fcntl.h> +#include <errno.h> #include "cpp.h" #include "y.tab.h" @@ -198,7 +199,14 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) { {D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); } {D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); } -^{WS}*#{WS}* { contr = 1; BEGIN CONTR; } +^{WS}*#{WS}* { extern int inmac; + + if (inmac) + error("preprocessor directive found " + "while expanding macro"); + contr = 1; + BEGIN CONTR; + } {WS}+ { PRTOUT(WSPACE); } <CONTR>"ifndef" { contr = 0; ifndefstmt(); } @@ -217,13 +225,13 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) { "//".*$ { /* if (tflag) yyless(..) */ - if (Cflag) + if (Cflag && !flslvl) putstr((usch *)yytext); else if (!flslvl) putch(' '); } "/*" { int c, wrn; - if (Cflag) + if (Cflag && !flslvl) putstr((usch *)yytext); wrn = 0; more: while ((c = input()) && c != '*') { @@ -231,20 +239,20 @@ L?'(\\.|[^\\'])+' { if (YYSTATE) { putch(c), ifiles->lineno++; else if (c == 1) /* WARN */ wrn = 1; - else if (Cflag) + else if (Cflag && !flslvl) putch(c); } if (c == 0) return 0; - if (Cflag) + if (Cflag && !flslvl) putch(c); if ((c = input()) && c != '/') { - if (Cflag) + if (Cflag && !flslvl) putch('*'); unput(c); goto more; } - if (Cflag) + if (Cflag && !flslvl) putch(c); if (c == 0) return 0; @@ -580,15 +588,23 @@ charcon(void) } static void -chknl(void) +chknl(int ignore) { int t; slow = 1; while ((t = yylex()) == WSPACE) ; - if (t != '\n') - error("newline expected, got \"%s\"", yytext); + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = yylex()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } slow = 0; } @@ -612,7 +628,7 @@ elsestmt(void) if (elslvl==trulvl+flslvl) error("Too many else"); elslvl=trulvl+flslvl; - chknl(); + chknl(1); } static void @@ -640,7 +656,7 @@ ifdefstmt(void) trulvl++; else flslvl++; - chknl(); + chknl(0); } static void @@ -659,7 +675,7 @@ ifndefstmt(void) trulvl++; else flslvl++; - chknl(); + chknl(0); } static void @@ -676,7 +692,7 @@ endifstmt(void) if (flslvl == 0) elflvl = 0; elslvl = 0; - chknl(); + chknl(1); } /* @@ -832,7 +848,7 @@ undefstmt(void) if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) np->value = 0; slow = 0; - chknl(); + chknl(0); } static void diff --git a/usr.bin/pcc/hppa/code.c b/usr.bin/pcc/hppa/code.c index f00c7639bf5..ebc523f57dd 100644 --- a/usr.bin/pcc/hppa/code.c +++ b/usr.bin/pcc/hppa/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.3 2007/12/19 20:19:54 otto Exp $ */ +/* $OpenBSD: code.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -32,38 +32,46 @@ # include "pass1.h" NODE *funarg(NODE *, int *); +int argreg(TWORD, int *); /* - * cause the alignment to become a multiple of n - * never called for text segment. + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. */ void -defalign(int n) +defloc(struct symtab *sp) { - n /= SZCHAR; - if (n == 1) - return; - printf("\t.align %d\n", n); -} + extern char *nextsect; + static char *loctbl[] = { "text", "data", "section .rodata" }; + static int lastloc = -1; + TWORD t; + int s; -/* - * define the current location as the name p->sname - * never called for text segment. - */ -void -defnam(struct symtab *p) -{ - char *c = p->sname; - -#ifdef GCC_COMPAT - c = gcc_findname(p); -#endif - if (p->sclass == EXTDEF) - printf("\t.export %s, data\n", c); - printf("\t.label %s\n", c); + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (nextsect) { + printf("\t.section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf("\t.%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + if (t > UCHAR) + printf("\t.align\t%d\n", ISFTN(t)? 4 : talign(t, sp->ssue)); + if (sp->sclass == EXTDEF) + printf("\t.export %s, data\n", sp->soname); + if (sp->slevel == 0) + printf("\t.label %s\n", sp->soname); + else + printf("\t.label\t" LABFMT "\n", sp->soffset); } - /* * code for the end of a function * deals with struct return here @@ -94,20 +102,71 @@ efcode() send_passt(IP_NODE, p); } +int +argreg(TWORD t, int *n) +{ + switch (t) { + case FLOAT: + return FR7L - 2 * (*n)++; + case DOUBLE: + case LDOUBLE: + *n += 2; + return FR6 - *n - 2; + case LONGLONG: + case ULONGLONG: + *n += 2; + return AD1 - (*n - 2) / 2; + default: + return ARG0 - (*n)++; + } +} + /* * 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 n) +bfcode(struct symtab **a, int cnt) { - int i; + struct symtab *sp; + NODE *p, *q; + int i, n, sz; - if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) - return; + 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(INT); + } + + /* 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); + } + } + } } @@ -138,40 +197,6 @@ bjobcode(void) } /* - * Print character t at position i in one string, until t == -1. - * Locctr & label is already defined. - */ -void -bycode(int t, int i) -{ - static int lastoctal = 0; - - /* put byte i+1 in a string */ - - if (t < 0) { - if (i != 0) - puts("\""); - } else { - if (i == 0) - printf("\t.ascii\t\""); - if (t == '\\' || t == '"') { - lastoctal = 0; - putchar('\\'); - putchar(t); - } else if (t < 040 || t >= 0177) { - lastoctal++; - printf("\\%o",t); - } else if (lastoctal && '0' <= t && t <= '9') { - lastoctal = 0; - printf("\"\n\t.ascii\t\"%c", t); - } else { - lastoctal = 0; - putchar(t); - } - } -} - -/* * return the alignment of field of type t */ int @@ -210,7 +235,7 @@ funarg(NODE *p, int *n) sz = szty(p->n_type); if (*n % sz) - (*n)++; /* XXX */ + (*n)++; /* XXX LDOUBLE */ if (*n >= 4) { *n += sz; @@ -221,25 +246,7 @@ funarg(NODE *p, int *n) } else { r = block(REG, NIL, NIL, p->n_type, 0, 0); r->n_lval = 0; - switch (p->n_type) { - case FLOAT: - r->n_rval = FR7L - 2 * (*n)++; - break; - case DOUBLE: - case LDOUBLE: - *n = (*n + 1) & ~1; - r->n_rval = FR6 - *n; - *n += 2; - break; - case LONGLONG: - case ULONGLONG: - *n = (*n + 1) & ~1; - r->n_rval = AD1 - *n / 2; - *n += 2; - break; - default: - r->n_rval = ARG0 - (*n)++; - } + r->n_rval = argreg(p->n_type, n); } p = block(ASSIGN, r, p, p->n_type, 0, 0); clocal(p); diff --git a/usr.bin/pcc/hppa/local.c b/usr.bin/pcc/hppa/local.c index 2c9fd3fa4a1..58ace34370c 100644 --- a/usr.bin/pcc/hppa/local.c +++ b/usr.bin/pcc/hppa/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.3 2007/12/19 20:19:54 otto Exp $ */ +/* $OpenBSD: local.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -34,6 +34,8 @@ /* this file contains code which is dependent on the target machine */ +struct symtab *makememcpy(void); + /* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. @@ -48,7 +50,7 @@ NODE * clocal(NODE *p) { - register struct symtab *q; + register struct symtab *q, *sp; register NODE *r, *l, *s; register int o, m, rn; char *ch, name[16]; @@ -113,13 +115,14 @@ clocal(NODE *p) case STATIC: case EXTERN: + if (strncmp(p->n_sp->soname, "__builtin", 9) == 0) + break; + l = block(REG, NIL, NIL, INT, 0, 0); l->n_lval = 0; l->n_rval = R1; l = block(ASSIGN, l, p, INT, 0, 0); - r = block(ICON, NIL, NIL, INT, 0, 0); - r->n_sp = p->n_sp; - r->n_lval = 0; + r = xbcon(0, p->n_sp, INT); p = block(UMUL, block(PLUS, l, r, INT, 0, 0), NIL, p->n_type, p->n_df, p->n_sue); @@ -135,9 +138,7 @@ clocal(NODE *p) l->n_lval = 0; l->n_rval = R1; l = block(ASSIGN, l, p->n_left, INT, 0, 0); - r = block(ICON, NIL, NIL, INT, 0, 0); - r->n_sp = p->n_left->n_sp; - r->n_lval = 0; + r = xbcon(0, p->n_left->n_sp, INT); l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue); nfree(p); p = l; @@ -285,7 +286,16 @@ clocal(NODE *p) l->n_sue = MKSUE(m); nfree(p); return l; + } else if (l->n_op == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return clocal(l); } + if (DEUNSIGN(p->n_type) == SHORT && DEUNSIGN(l->n_type) == SHORT) { nfree(p); @@ -384,6 +394,77 @@ clocal(NODE *p) p->n_type, p->n_df, p->n_sue); l->n_left = tcopy(r); break; + + case STASG: + /* memcpy(left, right, size) */ + sp = makememcpy(); + l = p->n_left; + /* guess struct return */ + if (l->n_op == NAME && ISFTN(l->n_sp->stype)) { + l = block(REG, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)); + l->n_lval = 0; + l->n_rval = RET0; + } else if (l->n_op == UMUL) + l = tcopy(l->n_left); + else if (l->n_op == NAME) + l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,MKSUE(LONG)); + l = block(CALL, block(ADDROF, + (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))), + NIL, PTR|FTN, 0, MKSUE(LONG)), + block(CM, block(CM, l, tcopy(p->n_right), + STRTY|PTR, 0, MKSUE(LONG)), + (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), + INT, 0, MKSUE(LONG)); + r->n_lval = p->n_sue->suesize/SZCHAR; + s->n_sp = sp; + s->n_df = s->n_sp->sdf; + defid(s, EXTERN); + tfree(p); + p = l; + p->n_left = clocal(p->n_left); + p->n_right = clocal(p->n_right); + calldec(p->n_left, p->n_right); + funcode(p); + break; + + case STARG: + /* arg = memcpy(argN-size, src, size) */ + sp = makememcpy(); + l = block(CALL, block(ADDROF, + (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),NIL,0,0,0), + block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0), + (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), + INT, 0, MKSUE(LONG)); + r->n_lval = p->n_sue->suesize/SZCHAR; + s->n_sp = sp; + s->n_df = s->n_sp->sdf; + defid(s, EXTERN); + tfree(p); + p = l; + p->n_left = clocal(p->n_left); + calldec(p->n_left, p->n_right); + funcode(p); + break; + + case STCALL: + case CALL: + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op == ASSIGN && + r->n_right->n_right->n_op == CALL) { + s = r->n_right->n_right; + l = tempnode(0, s->n_type, s->n_df, s->n_sue); + ecode(buildtree(ASSIGN, l, s)); + r->n_right->n_right = tcopy(l); + } + if (r->n_left->n_op == ASSIGN && + r->n_left->n_right->n_op == CALL) { + s = r->n_left->n_right; + l = tempnode(0, s->n_type, s->n_df, s->n_sue); + ecode(buildtree(ASSIGN, l, s)); + r->n_left->n_right = tcopy(l); + } + } + break; } /* second pass - rewrite long ops */ @@ -414,6 +495,7 @@ clocal(NODE *p) p->n_left->n_left->n_sp = lookup(addname(name), 0); defid(p->n_left->n_left, EXTERN); p->n_left = clocal(p->n_left); + calldec(p->n_left, p->n_right); p->n_op = CALL; funcode(p); break; @@ -428,9 +510,60 @@ clocal(NODE *p) return(p); } +struct symtab * +makememcpy() +{ + NODE *memcpy, *args, *t, *u; + struct symtab *sp; + + /* TODO check that it's a func proto */ + if ((sp = lookup(addname("memcpy"), SNORMAL))) + return sp; + + memcpy = block(NAME, NIL, NIL, 0, 0, MKSUE(LONG)); + memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL); + defid(memcpy, EXTERN); + + args = block(CM, block(CM, + block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), + block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 0, 0, 0), + block(NAME, NIL, NIL, LONG, 0, MKSUE(LONG)), 0, 0, 0); + + tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0), + (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0), + NIL, LONG, 0, 0))); + tfree(t); + tfree(u); + + return sp; +} + void myp2tree(NODE *p) { + int o = p->n_op; + + if (o != FCON) + return; + + /* Write float constants to memory */ + /* Should be volontary per architecture */ + +#if 0 + setloc1(RDATA); + defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ? + ALDOUBLE : ALLDOUBLE ); + deflab1(i = getlab()); +#endif + + ninval(0, btdims[p->n_type].suesize, p); + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = tmpalloc(sizeof(struct symtab_hdr)); + p->n_sp->sclass = ILABEL; + p->n_sp->soffset = getlab(); + p->n_sp->sflags = 0; + } /*ARGSUSED*/ @@ -540,9 +673,12 @@ indata(CONSZ val, int size) * sequences. Location is already set. */ void -instring(char *str) +instring(struct symtab *sp) { - char *s; + char *s, *str; + + defloc(sp); + str = sp->sname; /* be kind to assemblers and avoid long strings */ printf("\t.ascii\t\""); @@ -560,6 +696,27 @@ instring(char *str) printf("\\0\"\n"); } +/* + * Print out a wide string by calling ninval(). + */ +void +inwstring(struct symtab *sp) +{ + char *s = sp->sname; + NODE *p; + + defloc(sp); + p = bcon(0); + do { + if (*s++ == '\\') + p->n_lval = esccon(&s); + else + p->n_lval = (unsigned char)s[-1]; + ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p); + } while (s[-1] != 0); + nfree(p); +} + static int inbits, inval; /* @@ -660,7 +817,7 @@ ninval(CONSZ off, int fsz, NODE *p) q->sclass == ILABEL) { printf("+" LABFMT, q->soffset); } else - printf("+%s", exname(q->sname)); + printf("+%s", exname(q->soname)); } printf("\n"); break; @@ -719,71 +876,65 @@ ctype(TWORD type) } void -calldec(NODE *p, NODE *q) +calldec(NODE *f, NODE *a) { - printf("\t.call\n"); + struct symtab *q; + if (f->n_op == UMUL && f->n_left->n_op == PLUS && + f->n_left->n_right->n_op == ICON) + q = f->n_left->n_right->n_sp; + else if (f->n_op == PLUS && f->n_right->n_op == ICON) + q = f->n_right->n_sp; + else { + fwalk(f, eprint, 0); + cerror("unknown function"); + return; + } + + printf("\t.import\t%s,code\n", exname(q->soname)); } void extdec(struct symtab *q) { -#ifdef GCC_COMPAT - printf("\t.import\t%s,data\n", gcc_findname(q)); -#else - printf("\t.import\t%s,data\n", exname(q->sname)); -#endif + printf("\t.import\t%s,data\n", exname(q->soname)); } /* make a common declaration for id, if reasonable */ void -commdec(struct symtab *q) +defzero(struct symtab *sp) { int off; - off = tsize(q->stype, q->sdf, q->ssue); - off = (off+(SZCHAR-1))/SZCHAR; -#ifdef GCC_COMPAT - printf("\t.label\t%s\n", gcc_findname(q)); -#else - printf("\t.label\t%s\n", exname(q->sname)); -#endif - printf("\t.comm\t%d\n", off); + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off + (SZCHAR - 1)) / SZCHAR; + printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", exname(sp->soname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); } -/* make a local common declaration for id, if reasonable */ -void -lcommdec(struct symtab *q) -{ - int off; +char *nextsect; - off = tsize(q->stype, q->sdf, q->ssue); - off = (off+(SZCHAR-1))/SZCHAR; - if (q->slevel == 0) -#ifdef GCC_COMPAT - printf("\t.lcomm %s,0%o\n", gcc_findname(q), off); -#else - printf("\t.lcomm %s,0%o\n", exname(q->sname), off); -#endif - else - printf("\t.lcomm " LABFMT ",0%o\n", q->soffset, off); -} +#define SSECTION 010000 /* - * print a (non-prog) label. + * Give target the opportunity of handling pragmas. */ -void -deflab1(int label) +int +mypragma(char **ary) { - printf("\t.label\t" LABFMT "\n", label); + if (strcmp(ary[1], "section") || ary[2] == NULL) + return 0; + nextsect = newstring(ary[2], strlen(ary[2])); + return 1; } -static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" }; - +/* + * Called when a identifier has been declared, to give target last word. + */ void -setloc1(int locc) +fixdef(struct symtab *sp) { - if (locc == lastloc) - return; - lastloc = locc; - printf("\t.%s\n", loctbl[locc]); } + diff --git a/usr.bin/pcc/hppa/local2.c b/usr.bin/pcc/hppa/local2.c index feec2e85ccc..4bd2cd97093 100644 --- a/usr.bin/pcc/hppa/local2.c +++ b/usr.bin/pcc/hppa/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.3 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -86,18 +86,18 @@ prtprolog(struct interpass_prolog *ipp, int addto) for (i = 0; i < MAXREGS; i++) if (TESTBIT(ipp->ipp_regs, i)) { if (i <= R31) - printf("\tstw\t%s,%d(%%sp)\n", + printf("\tstw\t%s,%d(%%r3)\n", rnames[i], regoff[i]); else if (i <= RETD0) - printf("\tstw\t%s,%d(%%sp)\n" - "\tstw\t%s,%d(%%sp)\n", + printf("\tstw\t%s,%d(%%r3)\n" + "\tstw\t%s,%d(%%r3)\n", rnames[rl[i - RD0]], regoff[i] + 0, rnames[rh[i - RD0]], regoff[i] + 4); else if (i <= FR31) - printf("\tfstws\t%s,%d(%%sp)\n", + printf("\tfstws\t%s,%d(%%r3)\n", rnames[i], regoff[i]); else - printf("\tfstds\t%s,%d(%%sp)\n", + printf("\tfstds\t%s,%d(%%r3)\n", rnames[i], regoff[i]); } } @@ -108,7 +108,7 @@ prtprolog(struct interpass_prolog *ipp, int addto) static int offcalc(struct interpass_prolog *ipp) { - int i, addto; + int i, addto, off; addto = 32; if (p2calls) { @@ -119,12 +119,12 @@ offcalc(struct interpass_prolog *ipp) addto += i * 4; } - for (i = 0; i < MAXREGS; i++) + for (off = 4, i = 0; i < MAXREGS; i++) if (TESTBIT(ipp->ipp_regs, i)) { - regoff[i] = addto; - addto += SZINT/SZCHAR; + regoff[i] = off; + off += szty(PERMTYPE(i)) * SZINT/SZCHAR; } - addto += 4 + p2maxautooff; + addto += off + p2maxautooff; return (addto + 63) & ~63; } @@ -160,18 +160,18 @@ eoftn(struct interpass_prolog *ipp) for (i = 0; i < MAXREGS; i++) if (TESTBIT(ipp->ipp_regs, i)) { if (i <= R31) - printf("\tldw\t%d(%%sp),%s\n", + printf("\tldw\t%d(%%r3),%s\n", regoff[i], rnames[i]); else if (i <= RETD0) - printf("\tldw\t%d(%%sp),%s\n" - "\tldw\t%d(%%sp),%s\n", + printf("\tldw\t%d(%%r3),%s\n" + "\tldw\t%d(%%r3),%s\n", regoff[i] + 0, rnames[rl[i - RD0]], regoff[i] + 4, rnames[rh[i - RD0]]); else if (i <= FR31) - printf("\tfldws\t%d(%%sp),%s\n", + printf("\tfldws\t%d(%%r3),%s\n", regoff[i], rnames[i]); else - printf("\tfldds\t%d(%%sp),%s\n", + printf("\tfldds\t%d(%%r3),%s\n", regoff[i], rnames[i]); } @@ -285,7 +285,7 @@ tlen(p) NODE *p; default: if (!ISPTR(p->n_type)) - comperr("tlen type %d not pointer"); + comperr("tlen type %d not pointer", p->n_type); return SZPOINT(p->n_type)/SZCHAR; } } @@ -293,6 +293,7 @@ tlen(p) NODE *p; static int argsiz(NODE *p) { + NODE *q; TWORD t = p->n_type; if (t < LONGLONG || t == FLOAT || t > BTMASK) @@ -300,10 +301,16 @@ argsiz(NODE *p) if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) return 8; if (t == LDOUBLE) - return 8; /* quad is 16 */ - if (t == STRTY || t == UNIONTY) - return p->n_stsize; - comperr("argsiz"); + return 8; /* LDOUBLE is 16 */ + if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == STARG) + return 4 + p->n_right->n_stsize; + /* perhaps it's down there somewhere -- let me take another look! */ + if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == CALL) { + q = p->n_right->n_right->n_left->n_left->n_right; + if (q->n_op == STARG) + return 4 + q->n_stsize; + } + comperr("argsiz %p", p); return 0; } @@ -345,11 +352,19 @@ twollcomp(NODE *p) } 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(p->n_op, e); + if (cb1) { + p->n_op = cb1; + p->n_label = s; + expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); + p->n_label = e; + p->n_op = o; + } + if (cb2) { + p->n_op = cb2; + expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); + p->n_op = o; + } + expand(p, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n"); deflab(s); } @@ -554,7 +569,6 @@ adrput(FILE *io, NODE *p) } else fprintf(io, "(%s)", rnames[p->n_rval]); return; - case MOVE: case REG: if (RD0 <= p->n_rval && p->n_rval <= RETD0) fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]); diff --git a/usr.bin/pcc/hppa/macdefs.h b/usr.bin/pcc/hppa/macdefs.h index 65eedbd59ee..86aaccf741d 100644 --- a/usr.bin/pcc/hppa/macdefs.h +++ b/usr.bin/pcc/hppa/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.2 2007/12/19 20:19:54 otto Exp $ */ +/* $OpenBSD: macdefs.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff diff --git a/usr.bin/pcc/hppa/order.c b/usr.bin/pcc/hppa/order.c index 68513151ba1..e9dac7f575e 100644 --- a/usr.bin/pcc/hppa/order.c +++ b/usr.bin/pcc/hppa/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.2 2007/12/19 20:19:54 otto Exp $ */ +/* $OpenBSD: order.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -177,6 +177,7 @@ setorder(NODE *p) { return 0; /* nothing differs on hppa */ } + /* * Set registers "live" at function calls (like arguments in registers). * This is for liveness analysis of registers. @@ -184,9 +185,23 @@ setorder(NODE *p) int * livecall(NODE *p) { - static int r[1] = { -1 }; /* Terminate with -1 */ - - return &r[0]; + static int r[5], *s = &r[4]; + + *s = -1; + if (p->n_op == UCALL || p->n_op == UFORTCALL || p->n_op == USTCALL || + p->n_op == FORTCALL) + return s; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + if (p->n_right->n_op == ASSIGN && + p->n_right->n_left->n_op == REG) + *--s = p->n_right->n_left->n_rval; + + if (p->n_op == ASSIGN && + p->n_left->n_op == REG) + *--s = p->n_left->n_rval; + + return s; } /* diff --git a/usr.bin/pcc/hppa/table.c b/usr.bin/pcc/hppa/table.c index 71149fc9fae..5e53ef9736c 100644 --- a/usr.bin/pcc/hppa/table.c +++ b/usr.bin/pcc/hppa/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.2 2007/12/19 20:19:54 otto Exp $ */ +/* $OpenBSD: table.c,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -583,13 +583,13 @@ struct optab table[] = { { ASSIGN, FOREFF|INAREG, SOREG, TBYTE, - SHINT, TBYTE, + SHINT, TBYTE, 0, RDEST, "\tstb\tAR,AL\n", }, { ASSIGN, FOREFF|INAREG, SOREG, THWORD, - SHINT, THWORD, + SHINT, THWORD, 0, RDEST, "\tsth\tAR,AL\n", }, @@ -601,7 +601,7 @@ struct optab table[] = { { ASSIGN, FOREFF|INLL, SOREG, TLL, - SHLL, TLL, + SHLL, TLL, 0, RDEST, "\tstw\tAR,AL\n" "\tstw\tUR,UL\n", }, diff --git a/usr.bin/pcc/i386/code.c b/usr.bin/pcc/i386/code.c index 0e0a6bb7cbc..11f951ff1f2 100644 --- a/usr.bin/pcc/i386/code.c +++ b/usr.bin/pcc/i386/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.7 2008/01/12 17:29:09 ragge Exp $ */ +/* $OpenBSD: code.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -48,6 +48,13 @@ defloc(struct symtab *sp) } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; +#ifdef TLS + if (sp->sflags & STLS) { + if (s != DATA) + cerror("non-data symbol in tls section"); + nextsect = ".tdata"; + } +#endif if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; diff --git a/usr.bin/pcc/i386/local.c b/usr.bin/pcc/i386/local.c index 4643c7adbe1..9f3fe41cdd5 100644 --- a/usr.bin/pcc/i386/local.c +++ b/usr.bin/pcc/i386/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.6 2008/01/12 17:29:09 ragge Exp $ */ +/* $OpenBSD: local.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -123,6 +123,83 @@ picstatic(NODE *p) return q; } +#ifdef TLS +/* + * Create a reference for a TLS variable. + */ +static NODE * +tlspic(NODE *p) +{ + NODE *q, *r; + struct symtab *sp; + + /* + * creates: + * leal var@TLSGD(%ebx),%eax + * call ___tls_get_addr@PLT + */ + + /* calc address of var@TLSGD */ + q = tempnode(gotnr, PTR|VOID, 0, MKSUE(VOID)); + sp = picsymtab(p->n_sp->soname, "@TLSGD"); + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + /* assign to %eax */ + r = block(REG, NIL, NIL, PTR|VOID, 0, MKSUE(VOID)); + r->n_rval = EAX; + q = buildtree(ASSIGN, r, q); + + /* call ___tls_get_addr */ + spname = lookup("___tls_get_addr@PLT", 0); + spname->stype = EXTERN|INT|FTN; + r = buildtree(NAME, NIL, NIL); + r = buildtree(ADDROF, r, NIL); + r = block(UCALL, r, NIL, INT, 0, MKSUE(INT)); + + /* fusion both parts together */ + q = buildtree(COMOP, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); + q->n_sp = p->n_sp; /* for init */ + + nfree(p); + return q; +} + +static NODE * +tlsnonpic(NODE *p) +{ + NODE *q, *r; + struct symtab *sp; + int ext = p->n_sp->sclass; + + sp = picsymtab(p->n_sp->soname, ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF"); + q = xbcon(0, sp, INT); + if (ext == EXTERN) + q = block(UMUL, q, NIL, PTR|VOID, 0, MKSUE(VOID)); + + spname = lookup("%gs:0", 0); + spname->stype = EXTERN|INT; + r = buildtree(NAME, NIL, NIL); + + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); + q->n_sp = p->n_sp; /* for init */ + + nfree(p); + return q; +} + +static NODE * +tlsref(NODE *p) +{ + if (kflag) + return (tlspic(p)); + else + return (tlsnonpic(p)); +} +#endif + /* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. @@ -172,6 +249,12 @@ clocal(NODE *p) break; /* FALLTHROUGH */ case STATIC: +#ifdef TLS + if (q->sflags & STLS) { + p = tlsref(p); + break; + } +#endif if (kflag == 0) { if (q->slevel == 0) break; @@ -188,6 +271,12 @@ clocal(NODE *p) case EXTERN: case EXTDEF: +#ifdef TLS + if (q->sflags & STLS) { + p = tlsref(p); + break; + } +#endif if (kflag == 0) break; if (blevel > 0) @@ -374,6 +463,14 @@ clocal(NODE *p) l->n_sue = MKSUE(m); nfree(p); return l; + } else if (l->n_op == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return clocal(l); } if (DEUNSIGN(p->n_type) == SHORT && DEUNSIGN(l->n_type) == SHORT) { @@ -405,9 +502,10 @@ clocal(NODE *p) case PMCONV: case PVCONV: - if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); - nfree(p); - return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + r = p; + p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right); + nfree(r); + break; case FORCE: /* put return value in return reg */ @@ -846,6 +944,15 @@ defzero(struct symtab *sp) { int off; +#ifdef TLS + if (sp->sflags & STLS) { + if (sp->sclass == EXTERN) + sp->sclass = EXTDEF; + simpleinit(sp, bcon(0)); + return; + } +#endif + off = tsize(sp->stype, sp->sdf, sp->ssue); off = (off+(SZCHAR-1))/SZCHAR; printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); @@ -856,14 +963,21 @@ defzero(struct symtab *sp) } char *nextsect; - -#define SSECTION 010000 +#ifdef TLS +static int gottls; +#endif /* * Give target the opportunity of handling pragmas. */ int mypragma(char **ary) { +#ifdef TLS + if (strcmp(ary[1], "tls") == 0 && ary[2] == NULL) { + gottls = 1; + return 1; + } +#endif if (strcmp(ary[1], "section") || ary[2] == NULL) return 0; nextsect = newstring(ary[2], strlen(ary[2])); @@ -876,4 +990,10 @@ mypragma(char **ary) void fixdef(struct symtab *sp) { +#ifdef TLS + /* may have sanity checks here */ + if (gottls) + sp->sflags |= STLS; + gottls = 0; +#endif } diff --git a/usr.bin/pcc/i386/local2.c b/usr.bin/pcc/i386/local2.c index a2e02a69ec6..70015de2b29 100644 --- a/usr.bin/pcc/i386/local2.c +++ b/usr.bin/pcc/i386/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.7 2008/01/12 17:29:09 ragge Exp $ */ +/* $OpenBSD: local2.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -119,7 +119,7 @@ prologue(struct interpass_prolog *ipp) int addto; ftype = ipp->ipp_type; -#if 0 +#ifdef LANG_F77 if (ipp->ipp_vis) printf(" .globl %s\n", ipp->ipp_name); printf(" .align 4\n"); @@ -775,7 +775,6 @@ adrput(FILE *io, NODE *p) conput(io, p); return; - case MOVE: case REG: switch (p->n_type) { case LONGLONG: diff --git a/usr.bin/pcc/i386/macdefs.h b/usr.bin/pcc/i386/macdefs.h index 436b511152e..0343b1ffabc 100644 --- a/usr.bin/pcc/i386/macdefs.h +++ b/usr.bin/pcc/i386/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.3 2007/11/17 12:00:37 ragge Exp $ */ +/* $OpenBSD: macdefs.h,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -106,22 +106,14 @@ typedef long long OFFSZ; #define CONFMT "%lld" /* format for printing constants */ #define LABFMT ".L%d" /* format for printing labels */ #define STABLBL ".LL%d" /* format for stab (debugging) labels */ -#ifdef FORTRAN -#define XL 8 -#define FLABELFMT "%s:\n" -#define USETEXT ".text" -#define USECONST ".data\t0" /* XXX - fix */ -#define USEBSS ".data\t1" /* XXX - fix */ -#define USEINIT ".data\t2" /* XXX - fix */ -#define MAXREGVAR 3 /* XXX - fix */ +#ifdef LANG_F77 #define BLANKCOMMON "_BLNK_" #define MSKIREG (M(TYSHORT)|M(TYLONG)) #define TYIREG TYLONG #define FSZLENG FSZLONG -#define FUDGEOFFSET 1 #define AUTOREG EBP #define ARGREG EBP -#define ARGOFFSET 4 +#define ARGOFFSET 8 #endif #define BACKAUTO /* stack grows negatively for automatics */ @@ -304,3 +296,9 @@ int COLORMAP(int c, int *r); #define SMIXOR (MAXSPECIAL+4) #define SMILWXOR (MAXSPECIAL+5) #define SMIHWXOR (MAXSPECIAL+6) + +/* + * i386-specific symbol table flags. + */ +#define SSECTION SLOCAL1 +#define STLS SLOCAL2 diff --git a/usr.bin/pcc/i386/order.c b/usr.bin/pcc/i386/order.c index 95be8ab4461..f88ef1a4c67 100644 --- a/usr.bin/pcc/i386/order.c +++ b/usr.bin/pcc/i386/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.4 2007/12/09 18:53:02 ragge Exp $ */ +/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -280,9 +280,16 @@ setorder(NODE *p) int * livecall(NODE *p) { - static int r[2] = { EBX, -1 }; + static int r[] = { EAX, EBX, -1 }; + int off = 1; - return kflag ? &r[0] : &r[1]; +#ifdef TLS + if (p->n_left->n_op == ICON && + strcmp(p->n_left->n_name, "___tls_get_addr@PLT") == 0) + off--; +#endif + + return kflag ? &r[off] : &r[2]; } /* diff --git a/usr.bin/pcc/i386/table.c b/usr.bin/pcc/i386/table.c index 81c4ccb47af..8370d128171 100644 --- a/usr.bin/pcc/i386/table.c +++ b/usr.bin/pcc/i386/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: table.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -133,7 +133,7 @@ struct optab table[] = { { SCONV, INLL, SHCH|SOREG|SNAME, TCHAR, SANY, TLL, - NSPECIAL|NAREG|NASL, RESC1, + NSPECIAL|NCREG|NCSL, RESC1, " movsbl AL,%eax\n cltd\n", }, /* convert unsigned char to (u)long long */ @@ -275,14 +275,14 @@ struct optab table[] = { { SCONV, INCH, SOREG|SNAME, TLL, SANY, TCHAR|TUCHAR, - NAREG|NASL, RESC1, + NBREG|NBSL, RESC1, " movb AL,A1\n", }, /* convert (u)long long to (u)char (reg->reg, hopefully nothing) */ { SCONV, INCH, SHLL, TLL, SANY, TCHAR|TUCHAR, - NAREG|NASL, RESC1, + NBREG|NBSL, RESC1, "ZS", }, /* convert (u)long long to (u)short (mem->reg) */ @@ -1162,7 +1162,7 @@ struct optab table[] = { { UMUL, INLL, SANY, TANY, SOREG, TLL, - NCREG|NCSL, RESC1, + NCREG, RESC1, " movl UL,U1\n movl AL,A1\n", }, { UMUL, INAREG, diff --git a/usr.bin/pcc/mip/common.c b/usr.bin/pcc/mip/common.c index 399c8cb39ba..95ee5358394 100644 --- a/usr.bin/pcc/mip/common.c +++ b/usr.bin/pcc/mip/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.8 2007/11/17 12:00:37 ragge Exp $ */ +/* $OpenBSD: common.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -75,10 +75,19 @@ int nerrors = 0; /* number of errors */ char *ftitle; int lineno; +int warniserr = 0; + #ifndef WHERE #define WHERE(ch) fprintf(stderr, "%s, line %d: ", ftitle, lineno); #endif +static void +incerr(void) +{ + if (++nerrors > 30) + cerror("too many errors"); +} + /* * nonfatal error message * the routine where is different for pass 1 and pass 2; @@ -90,13 +99,11 @@ uerror(char *s, ...) va_list ap; va_start(ap, s); - ++nerrors; WHERE('u'); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); - if (nerrors > 30) - cerror("too many errors"); va_end(ap); + incerr(); } /* @@ -137,6 +144,8 @@ werror(char *s, ...) vfprintf(stderr, s, ap); fprintf(stderr, "\n"); va_end(ap); + if (warniserr) + incerr(); } #ifndef MKEXT @@ -191,7 +200,6 @@ tcopy(NODE *p) return(q); } - /* * ensure that all nodes have been freed */ @@ -317,7 +325,6 @@ struct dopest { { REG, "REG", LTYPE, }, { OREG, "OREG", LTYPE, }, { TEMP, "TEMP", LTYPE, }, - { MOVE, "MOVE", UTYPE, }, { ICON, "ICON", LTYPE, }, { FCON, "FCON", LTYPE, }, { CCODES, "CCODES", LTYPE, }, @@ -328,7 +335,8 @@ struct dopest { { UFORTCALL, "UFCALL", UTYPE|CALLFLG, }, { COMPL, "~", UTYPE, }, { FORCE, "FORCE", UTYPE, }, -/* { INIT, "INIT", UTYPE, }, */ + { XARG, "XARG", UTYPE, }, + { XASM, "XASM", BITYPE, }, { SCONV, "SCONV", UTYPE, }, { PCONV, "PCONV", UTYPE, }, { PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG, }, diff --git a/usr.bin/pcc/mip/manifest.h b/usr.bin/pcc/mip/manifest.h index b569f844366..a41278c8f0e 100644 --- a/usr.bin/pcc/mip/manifest.h +++ b/usr.bin/pcc/mip/manifest.h @@ -1,4 +1,4 @@ -/* $OpenBSD: manifest.h,v 1.9 2008/01/12 17:17:28 ragge Exp $ */ +/* $OpenBSD: manifest.h,v 1.10 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -167,6 +167,7 @@ #define DATA 1 /* (rw) data segment */ #define RDATA 2 /* (ro) data segment */ #define STRNG 3 /* (ro) string segment */ +#define UDATA 4 /* (rw) uninitialized data */ #define regno(p) ((p)->n_rval) /* register number */ @@ -177,7 +178,7 @@ extern int bdebug, tdebug, edebug; extern int ddebug, xdebug, f2debug; extern int iTflag, oTflag, kflag; -extern int sflag, nflag, gflag; +extern int sflag, nflag, gflag, pflag; extern int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int, Wimplicit_function_declaration; extern int xssaflag, xtailcallflag, xtemps, xdeljumps; @@ -319,4 +320,5 @@ NODE *tcopy(NODE *); void fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down); extern int nerrors; /* number of errors seen so far */ +extern int warniserr; /* treat warnings as errors */ #endif diff --git a/usr.bin/pcc/mip/match.c b/usr.bin/pcc/mip/match.c index e03b06ddb28..3204f429835 100644 --- a/usr.bin/pcc/mip/match.c +++ b/usr.bin/pcc/mip/match.c @@ -1,4 +1,4 @@ -/* $OpenBSD: match.c,v 1.8 2008/01/12 17:17:28 ragge Exp $ */ +/* $OpenBSD: match.c,v 1.9 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. diff --git a/usr.bin/pcc/mip/mkext.c b/usr.bin/pcc/mip/mkext.c index 609aae81cb6..f0fcdbde8fc 100644 --- a/usr.bin/pcc/mip/mkext.c +++ b/usr.bin/pcc/mip/mkext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mkext.c,v 1.7 2008/01/12 17:17:28 ragge Exp $ */ + /* * Generate defines for the needed hardops. */ @@ -67,7 +67,30 @@ int regclassmap[NUMCLASS][MAXREGS]; static void compl(struct optab *q, char *str) { - printf("table entry %td, op %s: %s\n", q - table, opst[q->op], str); + int op = q->op; + char *s; + + if (op < OPSIMP) { + s = opst[op]; + } else + s = "Special op"; + printf("table entry %td, op %s: %s\n", q - table, s, str); +} + +static int +getrcl(struct optab *q) +{ + int v = q->needs & (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT); + int r = q->rewrite & RESC1 ? 1 : q->rewrite & RESC2 ? 2 : 3; + int i = 0; + +#define INCK(c) while (v & c##COUNT) { \ + v -= c##REG, i++; if (i == r) return I##c##REG; } + INCK(NA) + INCK(NB) + INCK(NC) + INCK(ND) + return 0; } int @@ -147,6 +170,14 @@ main(int argc, char *argv[]) rval++; } } + /* check that reclaim is not the wrong class */ + if ((q->rewrite & (RESC1|RESC2|RESC3)) && + !(q->needs & REWRITE)) { + if ((q->visit & getrcl(q)) == 0) { + compl(q, "rwong RESCx class"); + rval++; + } + } if (q->rewrite & (RESC1|RESC2|RESC3) && q->visit & FOREFF) compl(q, "FOREFF may cause reclaim of wrong class"); } @@ -166,6 +197,19 @@ main(int argc, char *argv[]) fprintf(fc, "%d, ", i), j++; fprintf(fc, "-1 };\n"); fprintf(fh, "#define NPERMREG %d\n", j+1); + fprintf(fc, "bittype validregs[] = {\n"); + for (j = 0; j < MAXREGS; j += bitsz) { + int cbit = 0; + for (i = 0; i < bitsz; i++) { + if (i+j == MAXREGS) + break; + if (rstatus[i+j] & INREGS) + cbit |= (1 << i); + } + fprintf(fc, "\t0x%08x,\n", cbit); + } + fprintf(fc, "};\n"); + fprintf(fh, "extern bittype validregs[];\n"); /* * The register allocator uses bitmasks of registers for each class. diff --git a/usr.bin/pcc/mip/node.h b/usr.bin/pcc/mip/node.h index c21905bb422..ba7ce53be37 100644 --- a/usr.bin/pcc/mip/node.h +++ b/usr.bin/pcc/mip/node.h @@ -1,4 +1,4 @@ -/* $OpenBSD: node.h,v 1.2 2007/09/15 22:04:39 ray Exp $ */ +/* $OpenBSD: node.h,v 1.3 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -26,6 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef NODE_H +#define NODE_H + /* * The node structure is the basic element in the compiler. * Depending on the operator, it may be one of several types. @@ -113,7 +116,7 @@ typedef struct node { #define REG 6 #define OREG 7 #define TEMP 8 -#define MOVE 9 /* Special reg-reg move node */ +#define XARG 9 /* * Arithmetic nodes. @@ -184,7 +187,7 @@ typedef struct node { #define STASG 50 #define STARG 51 #define FORCE 52 -/* #define INIT 53 */ +#define XASM 53 #define GOTO 54 #define RETURN 55 #define STREF 56 @@ -192,3 +195,5 @@ typedef struct node { #define ADDROF 58 #define MAXOP 58 + +#endif diff --git a/usr.bin/pcc/mip/pass2.h b/usr.bin/pcc/mip/pass2.h index c1c922bd6f5..4b0c3b23b6a 100644 --- a/usr.bin/pcc/mip/pass2.h +++ b/usr.bin/pcc/mip/pass2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pass2.h,v 1.7 2007/12/09 18:38:49 ragge Exp $ */ +/* $OpenBSD: pass2.h,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -265,7 +265,7 @@ void myreader(struct interpass *pole); int oregok(NODE *p, int sharp); void myormake(NODE *); int *livecall(NODE *); - +void prtreg(FILE *, NODE *); char *prcook(int); void conput(FILE *, NODE *); diff --git a/usr.bin/pcc/mip/reader.c b/usr.bin/pcc/mip/reader.c index fd6a6339752..67292997d02 100644 --- a/usr.bin/pcc/mip/reader.c +++ b/usr.bin/pcc/mip/reader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: reader.c,v 1.13 2008/01/12 17:17:28 ragge Exp $ */ +/* $OpenBSD: reader.c,v 1.14 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -89,18 +89,13 @@ FILE *prfil; static struct interpass prepole; void saveip(struct interpass *ip); -void deljumps(void); void deltemp(NODE *p); -void mkhardops(NODE *p); -void optdump(struct interpass *ip); void cvtemps(struct interpass *epil); NODE *store(NODE *); -void rcount(void); -void compile2(struct interpass *ip); -void compile3(struct interpass *ip); -void compile4(struct interpass *ip); +static void fixxasm(struct interpass *ip); static void gencode(NODE *p, int cookie); +static void genxasm(NODE *p); char *ltyp[] = { "", "LREG", "LOREG", "LTEMP" }; char *rtyp[] = { "", "RREG", "ROREG", "RTEMP" }; @@ -117,13 +112,13 @@ static void cktree(NODE *p) { if (p->n_op > MAXOP) - cerror("op %d slipped through", p->n_op); + cerror("%p) op %d slipped through", p, p->n_op); if (BTYPE(p->n_type) > MAXTYPES) - cerror("type %x slipped through", p->n_type); + cerror("%p) type %x slipped through", p, p->n_type); if (p->n_op == CBRANCH && !logop(p->n_left->n_op)) - cerror("not logop branch"); + cerror("%p) not logop branch", p); if ((dope[p->n_op] & ASGOPFLG) && p->n_op != RETURN) - cerror("asgop %d slipped through", p->n_op); + cerror("%p) asgop %d slipped through", p, p->n_op); } #endif @@ -134,11 +129,11 @@ static int isuseless(NODE *n) { switch (n->n_op) { + case XASM: case FUNARG: case UCALL: case UFORTCALL: case FORCE: -/* case INIT: */ case ASSIGN: case CALL: case FORTCALL: @@ -245,6 +240,8 @@ pass2_compile(struct interpass *ip) } } + fixxasm(&ipole); /* setup for extended asm */ + optimize(&ipole); ngenregs(&ipole); @@ -290,6 +287,9 @@ emit(struct interpass *ip) case FORCE: gencode(p->n_left, INREGS); break; + case XASM: + genxasm(p); + break; default: if (p->n_op != REG || p->n_type != VOID) /* XXX */ gencode(p, FOREFF); /* Emit instructions */ @@ -309,10 +309,10 @@ emit(struct interpass *ip) deflab(ip->ip_lbl); break; case IP_ASM: - printf("\t%s\n", ip->ip_asm); + printf("%s", ip->ip_asm); break; default: - cerror("compile4 %d", ip->type); + cerror("emit %d", ip->type); } } @@ -476,6 +476,17 @@ again: switch (o = p->n_op) { p->n_su = 0; /* su calculations traverse left */ break; + case XASM: + for (p1 = p->n_left; p1->n_op == CM; p1 = p1->n_left) + geninsn(p1->n_right, FOREFF); + geninsn(p1, FOREFF); + break; /* all stuff already done? */ + + case XARG: + /* generate code for correct class here */ + geninsn(p->n_left, 1 << p->n_label); + break; + default: comperr("geninsn: bad op %s, node %p", opst[o], p); } @@ -576,6 +587,43 @@ rewrite(NODE *p, int rewrite, int cookie) p->n_rval = DECRA(p->n_reg, 0); } +/* + * printout extended assembler. + */ +void +genxasm(NODE *p) +{ + NODE *q, **nary; + int n = 1, o = 0; + char *w; + + for (q = p->n_left; q->n_op == CM; q = q->n_left) + n++; + nary = tmpalloc(sizeof(NODE *)*n); + o = n; + for (q = p->n_left; q->n_op == CM; q = q->n_left) { + gencode(q->n_right->n_left, INREGS); + nary[--o] = q->n_right; + } + gencode(q->n_left, INREGS); + nary[--o] = q; + + w = p->n_name; + putchar('\t'); + while (*w != 0) { + if (*w == '%') { + if (w[1] < '1' || w[1] > (n + '0')) + uerror("bad xasm arg number"); + else + adrput(stdout, nary[(int)w[1]-'1']->n_left); + w++; + } else + putchar(*w); + w++; + } + putchar('\n'); +} + void gencode(NODE *p, int cookie) { @@ -736,6 +784,11 @@ e2print(NODE *p, int down, int *a, int *b) fprintf(prfil, " %d", regno(p)); break; + case XASM: + case XARG: + fprintf(prfil, " '%s'", p->n_name); + break; + case ICON: case NAME: case OREG: @@ -755,16 +808,8 @@ e2print(NODE *p, int down, int *a, int *b) fprintf(prfil, ", " ); tprint(prfil, p->n_type, p->n_qual); fprintf(prfil, ", " ); - { - int gregn(struct regw *); - if (p->n_reg == -1) - fprintf(prfil, "REG <undef>"); - else if (0 <= p->n_reg && - p->n_reg < (ENCRD(MAXREGS) + ENCRA(MAXREGS,0))) /* XXX */ - fprintf(prfil, "REG %s", rnames[DECRA(p->n_reg, 0)]); - else - fprintf(prfil, "TEMP %d", gregn(p->n_regw)); - } + + prtreg(prfil, p); fprintf(prfil, ", SU= %d(%cREG,%s,%s,%s,%s)\n", TBLIDX(p->n_su), TCLASS(p->n_su)+'@', @@ -844,7 +889,7 @@ void deltemp(NODE *p) { struct tmpsave *w; - NODE *l; + NODE *l, *r; if (p->n_op == TEMP) { /* Check if already existing */ @@ -859,9 +904,10 @@ deltemp(NODE *p) w->next = tmpsave; tmpsave = w; } - p->n_op = OREG; - p->n_rval = FPREG; - p->n_lval = w->tempaddr; + l = mklnode(REG, 0, FPREG, INCREF(p->n_type)); + r = mklnode(ICON, w->tempaddr, 0, INT); + p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type)); + p->n_op = UMUL; } else if (p->n_op == ADDROF && p->n_left->n_op != NAME) { /* TEMPs are already converted to OREGs */ if ((l = p->n_left)->n_op != OREG) @@ -1021,6 +1067,12 @@ comperr(char *str, ...) extern char *ftitle; va_list ap; + if (nerrors) { + fprintf(stderr, + "cannot recover from earlier errors: goodbye!\n"); + exit(1); + } + va_start(ap, str); fprintf(stderr, "%s, line %d: compiler error: ", ftitle, thisline); vfprintf(stderr, str, ap); @@ -1134,3 +1186,68 @@ rspecial(struct optab *q, int what) } return -1; } + +/* + * Ensure that a node is correct for the destination. + */ +static void +ltypify(struct interpass *ip, NODE *p) +{ + struct interpass *ip2; + TWORD t = p->n_left->n_type; + NODE *q, *r; + char *w; +// int asg = 0, and = 0; + +#ifdef notyet + if (myxasm(ip, p)) + return; /* handled by target-specific code */ +#endif + w = p->n_name; +// if (*w == '=') +// w++, asg = 1; + switch (*w) { + case 'r': /* general reg */ + /* set register class */ + p->n_label = gclass(p->n_left->n_type); + if (optype(p->n_left->n_op) == LTYPE) + break; + q = mklnode(TEMP, 0, epp->ip_tmpnum++, t); + r = tcopy(q); + ip2 = ipnode(mkbinode(ASSIGN, q, p->n_left, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + p->n_left = r; + break; + default: + uerror("unsupported xasm option string '%s'", p->n_name); + } + + +// fwalk(p, e2print, 0); +} + +/* Extended assembler hacks */ +static void +fixxasm(struct interpass *ipole) +{ + struct interpass *ip; + NODE *p; + + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE || ip->ip_node->n_op != XASM) + continue; + /* Got an assembler node */ + p = ip->ip_node->n_left; + + /* + * Ensure that the arg nodes can be directly addressable + * We decide that everything shall be LTYPE here. + */ + for (; p->n_op == CM; p = p->n_left) + ltypify(ip, p->n_right); + ltypify(ip, p); + p = ip->ip_node->n_right; + if (p->n_op != ICON || p->n_type != STRTY) + uerror("xasm constraints not supported"); + } +} diff --git a/usr.bin/pcc/mip/regs.c b/usr.bin/pcc/mip/regs.c index e87069d6a15..55f605a3629 100644 --- a/usr.bin/pcc/mip/regs.c +++ b/usr.bin/pcc/mip/regs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: regs.c,v 1.15 2008/01/12 17:17:28 ragge Exp $ */ +/* $OpenBSD: regs.c,v 1.16 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2005 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -125,6 +125,7 @@ static REGW precolored, simplifyWorklist, freezeWorklist, spillWorklist, static REGW initial, *nblock; static void insnwalk(NODE *p); #ifdef PCC_DEBUG +int use_regw; int nodnum = 100; #define SETNUM(x) (x)->nodnum = nodnum++ #define ASGNUM(x) (x)->nodnum @@ -803,6 +804,8 @@ setlive(NODE *p, int set, REGW *rv) static void addedge_r(NODE *p, REGW *w) { + RRDEBUG(("addedge_r: node %p regw %p\n", p, w)); + if (p->n_regw != NULL) { AddEdge(p->n_regw, w); return; @@ -846,6 +849,7 @@ insnwalk(NODE *p) int o = p->n_op; struct optab *q = &table[TBLIDX(p->n_su)]; REGW *lr, *rr, *rv, *r, *rrv, *lrv; + NODE *lp, *rp; int i, n; RDEBUG(("insnwalk %p\n", p)); @@ -881,7 +885,9 @@ insnwalk(NODE *p) /* Check leaves for results in registers */ lr = optype(o) != LTYPE ? p->n_left->n_regw : NULL; + lp = optype(o) != LTYPE ? p->n_left : NULL; rr = optype(o) == BITYPE ? p->n_right->n_regw : NULL; + rp = optype(o) == BITYPE ? p->n_right : NULL; /* simple needs */ n = ncnt(q->needs); @@ -947,6 +953,13 @@ insnwalk(NODE *p) } if (o == ASSIGN) { + /* avoid use of unhandled registers */ + if (p->n_left->n_op == REG && + !TESTBIT(validregs, regno(p->n_left))) + lr = NULL; + if (p->n_right->n_op == REG && + !TESTBIT(validregs, regno(p->n_right))) + rr = NULL; /* needs special treatment */ if (lr && rr) moveadd(lr, rr); @@ -967,13 +980,13 @@ insnwalk(NODE *p) } else if (q->rewrite & RLEFT) { if (lr && rv) moveadd(rv, lr), lrv = rv; - if (rr && rv) - AddEdge(rr, rv); + if (rv && rp) + addedge_r(rp, rv); } else if (q->rewrite & RRIGHT) { if (rr && rv) moveadd(rv, rr), rrv = rv; - if (lr && rv) - AddEdge(lr, rv); + if (rv && lp) + addedge_r(lp, rv); } switch (optype(o)) { @@ -1734,14 +1747,6 @@ SelectSpill(void) FreezeMoves(w); } -int gregn(REGW *); - -int -gregn(REGW *w) -{ - return w->nodnum; -} - /* * Set class on long-lived temporaries based on its type. */ @@ -2104,6 +2109,33 @@ RewriteProgram(struct interpass *ip) return rwtyp; } +#ifdef PCC_DEBUG +/* + * Print TEMP/REG contents in a node. + */ +void +prtreg(FILE *fp, NODE *p) +{ + int i, n = p->n_su == -1 ? 0 : ncnt(table[TBLIDX(p->n_su)].needs); + + if (use_regw) { + fprintf(fp, "TEMP "); + if (p->n_regw != NULL) { + for (i = 0; i < n+1; i++) + fprintf(fp, "%d ", p->n_regw[i].nodnum); + } else + fprintf(fp, "<undef>"); + } else { + fprintf(fp, "REG "); + if (p->n_reg != -1) { + for (i = 0; i < n+1; i++) + fprintf(fp, "%s ", rnames[DECRA(p->n_reg, i)]); + } else + fprintf(fp, "<undef>"); + } +} +#endif + #ifdef notyet /* * Assign instructions, calculate evaluation order and @@ -2222,7 +2254,9 @@ onlyperm: /* XXX - should not have to redo all */ RDEBUG(("nsucomp allocated %d temps (%d,%d)\n", tempmax-tempmin, tempmin, tempmax)); + use_regw = 1; RPRINTIP(ipole); + use_regw = 0; RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin, tempmin, tempmax)); diff --git a/usr.bin/pcc/mips/code.c b/usr.bin/pcc/mips/code.c index be0830362ac..fcb0ec0cd75 100644 --- a/usr.bin/pcc/mips/code.c +++ b/usr.bin/pcc/mips/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: code.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -36,6 +36,45 @@ #include "pass1.h" /* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + static char *loctbl[] = { "text", "data", "section .rodata" }; + static int lastloc = -1; + TWORD t; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + lastloc = s; + if (s == PROG) + return; /* text is written in prologue() */ + if (s != lastloc) + printf(" .%s\n", loctbl[s]); + printf(" .p2align %d\n", ispow2(talign(t, sp->ssue))); + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", sp->soname); + if (sp->slevel == 0) { +#ifdef USE_GAS + printf("\t.type %s,@object\n", sp->soname); + printf("\t.size %s," CONFMT "\n", sp->soname, + tsize(sp->stype, sp->sdf, sp->ssue)); +#endif + printf("%s:\n", sp->soname); + } else + printf(LABFMT ":\n", sp->soffset); +} + + +#ifdef notdef +/* * cause the alignment to become a multiple of n * never called for text segment. */ @@ -55,11 +94,8 @@ defalign(int n) void defnam(struct symtab *p) { - char *c = p->sname; + char *c = p->soname; -#ifdef GCC_COMPAT - c = gcc_findname(p); -#endif if (p->sclass == EXTDEF) printf("\t.globl %s\n", c); #ifdef USE_GAS @@ -68,6 +104,7 @@ defnam(struct symtab *p) #endif printf("%s:\n", c); } +#endif static int rvnr; @@ -90,7 +127,7 @@ efcode() q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue); q->n_rval = V0; p = tempnode(0, INCREF(ty), 0, cftnsp->ssue); - tempnr = p->n_lval; + tempnr = regno(p); p = buildtree(ASSIGN, p, q); ecomp(p); @@ -119,7 +156,7 @@ putintemp(struct symtab *sym) spname = sym; p = tempnode(0, sym->stype, sym->sdf, sym->ssue); p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); - sym->soffset = p->n_left->n_lval; + sym->soffset = regno(p->n_left); sym->sflags |= STNODE; ecomp(p); } @@ -132,7 +169,7 @@ param_retptr(void) NODE *p, *q; p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); - rvnr = p->n_lval; + rvnr = regno(p); q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); q->n_rval = A0; p = buildtree(ASSIGN, p, q); @@ -200,7 +237,7 @@ param_64bit(struct symtab *sym, int *regp, int dotemps) q->n_rval = A0A1 + (reg - A0); if (dotemps) { p = tempnode(0, sym->stype, sym->sdf, sym->ssue); - sym->soffset = p->n_lval; + sym->soffset = regno(p); sym->sflags |= STNODE; } else { spname = sym; @@ -222,7 +259,7 @@ param_32bit(struct symtab *sym, int *regp, int dotemps) q->n_rval = (*regp)++; if (dotemps) { p = tempnode(0, sym->stype, sym->sdf, sym->ssue); - sym->soffset = p->n_lval; + sym->soffset = regno(p); sym->sflags |= STNODE; } else { spname = sym; @@ -262,7 +299,7 @@ param_double(struct symtab *sym, int *regp, int dotemps) } t = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG)); - tmpnr = t->n_lval; + tmpnr = regno(t); q = block(REG, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG)); q->n_rval = A0A1 + (reg - A0); p = buildtree(ASSIGN, t, q); @@ -293,7 +330,7 @@ param_float(struct symtab *sym, int *regp, int dotemps) int tmpnr; t = tempnode(0, INT, 0, MKSUE(INT)); - tmpnr = t->n_lval; + tmpnr = regno(t); q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); q->n_rval = (*regp)++; p = buildtree(ASSIGN, t, q); @@ -406,6 +443,7 @@ bjobcode() printf("\t.abicalls\n"); } +#ifdef notdef /* * Print character t at position i in one string, until t == -1. * Locctr & label is already defined. @@ -445,6 +483,7 @@ bycode(int t, int i) } } } +#endif /* * return the alignment of field of type t @@ -495,7 +534,7 @@ movearg_struct(NODE *p, NODE *parent, int *regp) nfree(p); ty = l->n_type; t = tempnode(0, l->n_type, l->n_df, l->n_sue); - tmpnr = t->n_lval; + tmpnr = regno(t); l = buildtree(ASSIGN, t, l); if (p != parent) { @@ -620,7 +659,7 @@ moveargs(NODE *p, int *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, MKSUE(LONGLONG)); - int tmpnr = t1->n_lval; + int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); t1 = movearg_64bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_sue); @@ -633,7 +672,7 @@ moveargs(NODE *p, int *regp) } else if (r->n_type == FLOAT) { /* XXX bounce in and out of temporary to change to int */ NODE *t1 = tempnode(0, INT, 0, MKSUE(INT)); - int tmpnr = t1->n_lval; + int tmpnr = regno(t1); NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); t1 = movearg_32bit(t1, regp); r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_sue); diff --git a/usr.bin/pcc/mips/local.c b/usr.bin/pcc/mips/local.c index 4c8a43f0f47..052e7de3fea 100644 --- a/usr.bin/pcc/mips/local.c +++ b/usr.bin/pcc/mips/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.5 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -75,7 +75,7 @@ clocal(NODE *p) if (p->n_type == PTR+VOID) isptrvoid = 1; r = tempnode(0, p->n_type, p->n_df, p->n_sue); - tmpnr = r->n_lval; + tmpnr = regno(r); r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_sue); p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); @@ -348,6 +348,28 @@ clocal(NODE *p) void myp2tree(NODE *p) { + struct symtab *sp; + + if (p->n_op != FCON) + return; + + /* Write float constants to memory */ + + sp = tmpalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, btdims[p->n_type].suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + } /*ARGSUSED*/ @@ -484,7 +506,7 @@ ninval(CONSZ off, int fsz, NODE *p) q->sclass == ILABEL) { printf("+" LABFMT, q->soffset); } else - printf("+%s", exname(q->sname)); + printf("+%s", exname(q->soname)); } printf("\n"); break; @@ -563,6 +585,73 @@ extdec(struct symtab *q) { } +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +/* + * Print out a wide string by calling ninval(). + */ +void +inwstring(struct symtab *sp) +{ + char *s = sp->sname; + NODE *p; + + defloc(sp); + p = bcon(0); + do { + if (*s++ == '\\') + p->n_lval = esccon(&s); + else + p->n_lval = (unsigned char)s[-1]; + ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p); + } while (s[-1] != 0); + nfree(p); +} + +/* make a common declaration for id, if reasonable */ +void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", exname(sp->soname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + + +#ifdef notdef /* make a common declaration for id, if reasonable */ void commdec(struct symtab *q) @@ -572,11 +661,7 @@ commdec(struct symtab *q) off = tsize(q->stype, q->sdf, q->ssue); off = (off+(SZCHAR-1))/SZCHAR; -#ifdef GCC_COMPAT - printf(" .comm %s,%d\n", gcc_findname(q), off); -#else - printf(" .comm %s,%d\n", exname(q->sname), off); -#endif + printf(" .comm %s,%d\n", exname(q->soname), off); } /* make a local common declaration for id, if reasonable */ @@ -588,11 +673,7 @@ lcommdec(struct symtab *q) off = tsize(q->stype, q->sdf, q->ssue); off = (off+(SZCHAR-1))/SZCHAR; if (q->slevel == 0) -#ifdef GCC_COMPAT - printf("\t.lcomm %s,%d\n", gcc_findname(q), off); -#else - printf("\t.lcomm %s,%d\n", exname(q->sname), off); -#endif + printf("\t.lcomm %s,%d\n", exname(q->soname), off); else printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off); } @@ -625,6 +706,7 @@ setloc1(int locc) if (locc == STRNG) printf("\t.align 2\n"); } +#endif /* * Initialize a bitfield. @@ -770,7 +852,7 @@ mips_builtin_va_arg(NODE *f, NODE *a) /* create a copy to a temp node */ p = tcopy(a->n_left); q = tempnode(0, p->n_type, p->n_df, p->n_sue); - tmpnr = q->n_lval; + tmpnr = regno(q); p = buildtree(ASSIGN, q, p); r = a->n_right; @@ -821,3 +903,19 @@ bad: uerror("bad argument to __buildtin_va_copy"); return bcon(0); } +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char **ary) +{ + return 0; } + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + diff --git a/usr.bin/pcc/mips/local2.c b/usr.bin/pcc/mips/local2.c index 9ff1ed1eafc..0b85505670f 100644 --- a/usr.bin/pcc/mips/local2.c +++ b/usr.bin/pcc/mips/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -755,7 +755,7 @@ fldexpand(NODE *p, int cookie, char **cp) break; case 'M': case 'N': - val = 1 << UPKFSZ(p->n_rval); + val = (CONSZ)1 << UPKFSZ(p->n_rval); --val; val <<= UPKFOFF(p->n_rval); printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff); @@ -928,7 +928,6 @@ adrput(FILE * io, NODE * p) conput(io, p); return; - case MOVE: case REG: if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC) print_reg64name(io, p->n_rval, 0); diff --git a/usr.bin/pcc/mips/macdefs.h b/usr.bin/pcc/mips/macdefs.h index c892c6e5faf..84d173b8788 100644 --- a/usr.bin/pcc/mips/macdefs.h +++ b/usr.bin/pcc/mips/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.4 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: macdefs.h,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. diff --git a/usr.bin/pcc/mips/order.c b/usr.bin/pcc/mips/order.c index 29c28ec5e64..df05ba7ac55 100644 --- a/usr.bin/pcc/mips/order.c +++ b/usr.bin/pcc/mips/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. diff --git a/usr.bin/pcc/mips/table.c b/usr.bin/pcc/mips/table.c index 48c2f3f9872..2839d163265 100644 --- a/usr.bin/pcc/mips/table.c +++ b/usr.bin/pcc/mips/table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: table.c,v 1.4 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: table.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. diff --git a/usr.bin/pcc/powerpc/code.c b/usr.bin/pcc/powerpc/code.c index 74a6025b37d..bc9a54cea42 100644 --- a/usr.bin/pcc/powerpc/code.c +++ b/usr.bin/pcc/powerpc/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.7 2007/12/28 12:32:55 stefan Exp $ */ +/* $OpenBSD: code.c,v 1.8 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -32,160 +32,464 @@ #include "pass1.h" #include "pass2.h" +static void genswitch_bintree(int num, TWORD ty, struct swents **p, int n); + #if 0 -static void genswitch_simple(int num, struct swents **p, int n); -static void genswitch_bintree(int num, struct swents **p, int n); static void genswitch_table(int num, struct swents **p, int n); static void genswitch_mrst(int num, struct swents **p, int n); #endif +int lastloc = -1; + +static int rvnr; + /* - * cause the alignment to become a multiple of n - * never called for text segment. + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. */ void -defalign(int n) +defloc(struct symtab *sp) { - if ((n = ispow2(n / SZCHAR)) == -1) +#if defined(ELFABI) + static char *loctbl[] = { "text", "data", "rodata" }; +#elif defined(MACHOABI) + static char *loctbl[] = { "text", "data", "const_data" }; +#endif + TWORD t; + int s, n; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + + if (s == PROG) + n = 2; + else if ((n = ispow2(talign(t, sp->ssue) / SZCHAR)) == -1) cerror("defalign: n != 2^i"); printf(" .p2align %d\n", n); + + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", exname(sp->soname)); + if (sp->slevel == 0) + printf("%s:\n", exname(sp->soname)); + else + printf(LABFMT ":\n", sp->soffset); } -/* - * define the current location as the name p->sname - * never called for text segment. +/* Put a symbol in a temporary + * used by bfcode() and its helpers */ -void -defnam(struct symtab *p) +static void +putintemp(struct symtab *sym) { - char *c = p->sname; + NODE *p; + + spname = sym; + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); +} -#ifdef GCC_COMPAT - c = gcc_findname(p); +/* setup a 64-bit parameter (double/ldouble/longlong) + * used by bfcode() */ +static void +param_64bit(struct symtab *sym, int *argoffp, int dotemps) +{ + int argoff = *argoffp; + NODE *p, *q; + int navail; + +#if ALLONGLONG == 64 + /* alignment */ + ++argoff; + argoff &= ~1; #endif - if (p->sclass == EXTDEF) - printf(" .globl %s\n", exname(c)); - printf("%s:\n", exname(c)); + + navail = NARGREGS - argoff; + + if (navail < 2) { + /* half in and half out of the registers */ + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R3 + argoff; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(sym->soffset/SZCHAR), PTR+INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + } else { + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R3R4 + argoff; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + spname = sym; + p = buildtree(NAME, 0, 0); + } + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argoffp = argoff + 2; } +/* setup a 32-bit param on the stack + * used by bfcode() */ +static void +param_32bit(struct symtab *sym, int *argoffp, int dotemps) +{ + NODE *p, *q; + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R3 + (*argoffp)++; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + spname = sym; + p = buildtree(NAME, 0, 0); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); +} -/* - * code for the end of a function - * deals with struct return here - */ -void -efcode() +/* setup a double param on the stack + * used by bfcode() */ +static void +param_double(struct symtab *sym, int *argoffp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + /* + * we have to dump the double 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. + */ + + if (xtemps) { + q = block(REG, NIL, NIL, ULONGLONG, 0, MKSUE(ULONGLONG)); + regno(q) = R3R4 + *argoffp; + p = block(REG, NIL, NIL, PTR+ULONGLONG, 0, MKSUE(ULONGLONG)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-8), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, ULONGLONG, 0, MKSUE(ULONGLONG)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + t = tempnode(0, sym->stype, sym->sdf, sym->ssue); + tmpnr = regno(t); + p = block(REG, NIL, NIL, + INCREF(sym->stype), sym->sdf, sym->ssue); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-8), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->ssue); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } else { + /* bounce straight into temp */ + p = block(REG, NIL, NIL, ULONGLONG, 0, MKSUE(ULONGLONG)); + regno(p) = R3R4 + *argoffp; + t = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG)); + tmpnr = regno(t); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } + + (*argoffp) += 2; + + sym->soffset = tmpnr; + sym->sflags |= STNODE; +} + +/* setup a float param on the stack + * used by bfcode() */ +static void +param_float(struct symtab *sym, int *argoffp, 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. + */ + + if (xtemps) { + /* bounce onto TOS */ + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R3 + (*argoffp); + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-4), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + t = tempnode(0, sym->stype, sym->sdf, sym->ssue); + tmpnr = regno(t); + p = block(REG, NIL, NIL, INCREF(sym->stype), + sym->sdf, sym->ssue); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-4), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->ssue); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } else { + /* bounce straight into temp */ + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = R3 + (*argoffp); + t = tempnode(0, INT, 0, MKSUE(INT)); + tmpnr = regno(t); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } + + (*argoffp)++; + + sym->soffset = tmpnr; + sym->sflags |= STNODE; +} + +/* setup the hidden pointer to struct return parameter + * used by bfcode() */ +static void +param_retstruct(void) { -#if 0 NODE *p, *q; - int sz; -#endif -#if 0 - printf("EFCODE:\n"); -#endif + /* XXX what if it is a union? */ + p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); + rvnr = regno(p); + q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + regno(q) = R3; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} - if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) - return; - assert(0); -#if 0 - /* 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, MKSUE(CHAR+PTR)); - p->n_rval = EAX; - q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); - q->n_rval = EBP; - q->n_lval = 8; /* return buffer offset */ - p = block(CM, q, p, INT, 0, MKSUE(INT)); - sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; - p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT)); - p->n_right->n_name = ""; - p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR)); - p->n_left->n_name = "memcpy"; - p = clocal(p); - send_passt(IP_NODE, p); -#endif + +/* setup struct parameter + * push the registers out to memory + * used by bfcode() */ +static void +param_struct(struct symtab *sym, int *argoffp) +{ + int argoff = *argoffp; + NODE *p, *q; + int navail; + int sz; + int off; + int num; + int i; + + navail = NARGREGS - argoff; + sz = tsize(sym->stype, sym->sdf, sym->ssue) / SZINT; + off = ARGINIT/SZINT + argoff; + num = sz > navail ? navail : sz; + for (i = 0; i < num; i++) { + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R3 + argoff++; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(4*off++), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + *argoffp = argoff; } /* - * code for the beginning of a function; a is an array of - * indices in symtab for the arguments; n is the number + * code for the beginning of a function + * sp is an array of indices in symtab for the arguments + * cnt is the number of arguments */ void -bfcode(struct symtab **a, int n) +bfcode(struct symtab **sp, int cnt) { - int i, m; - -#if 0 - printf("BFCODE start with %d arguments\n", n); +#ifdef USE_GOTNR + extern int gotnr; #endif - 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(INT); + union arglist *usym; + int saveallargs = 0; + int i, argoff = 0; + + /* + * Detect if this function has ellipses and save all + * argument registers onto stack. + */ + usym = cftnsp->sdf->dfun; + while (usym && usym->type != TNULL) { + if (usym->type == TELLIPSIS) { + saveallargs = 1; + break; + } + ++usym; + } + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + param_retstruct(); + ++argoff; } - m = n <= 8 ? n : 8; - -#if 0 - /* if optimised, assign parameters to registers */ - /* XXX consider the size of the types */ - for (i=0; i < m; i++) { - a[i]->hdr.h_sclass = REGISTER; - a[i]->hdr.h_offset = R3 + i; +#ifdef USE_GOTNR + if (kflag) { + /* put GOT register into temporary */ + NODE *q, *p; + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = GOTREG; + p = tempnode(0, INT, 0, MKSUE(INT)); + gotnr = regno(p); + ecomp(buildtree(ASSIGN, p, q)); } #endif - /* if not optimised, */ - /* save the register arguments (R3-R10) onto the stack */ - int passedargoff = ARGINIT + FIXEDSTACKSIZE*8; // XXX must add the size of the stack frame - int reg = R3; - for (i=0; i < m; i++) { - NODE *r, *p; - a[i]->sclass = PARAM; - a[i]->soffset = NOOFFSET; - oalloc(a[i], &passedargoff); - spname = a[i]; - p = buildtree(NAME, NIL, NIL); - r = bcon(0); - r->n_op = REG; - if (BTYPE(p->n_type) == LONGLONG || BTYPE(p->n_type) == ULONGLONG) { - r->n_rval = R3R4+(reg-R3); - reg += 2; - } else { - r->n_rval = reg++; + /* recalculate the arg offset and create TEMP moves */ + for (i = 0; i < cnt; i++) { + + if (sp[i] == NULL) + continue; + + if ((argoff >= NARGREGS) && !xtemps) + break; + + if (argoff >= NARGREGS) { + putintemp(sp[i]); + } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) { + param_struct(sp[i], &argoff); + } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) { + param_64bit(sp[i], &argoff, xtemps && !saveallargs); + } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + param_double(sp[i], &argoff, + xtemps && !saveallargs); + else + param_64bit(sp[i], &argoff, + xtemps && !saveallargs); + } else if (sp[i]->stype == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + param_float(sp[i], &argoff, + xtemps && !saveallargs); + else + param_32bit(sp[i], &argoff, + xtemps && !saveallargs); + } else { + param_32bit(sp[i], &argoff, xtemps && !saveallargs); } - r->n_type = p->n_type; - r->n_sue = p->n_sue; - r->n_df = p->n_df; - ecode(buildtree(ASSIGN, p, r)); + } + + /* if saveallargs, save the rest of the args onto the stack */ + while (saveallargs && argoff < NARGREGS) { + NODE *p, *q; + /* int off = (ARGINIT+FIXEDSTACKSIZE*SZCHAR)/SZINT + argoff; */ + int off = ARGINIT/SZINT + argoff; + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R3 + argoff++; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(4*off), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); } -#if 1 - /* XXXHACK save the rest of the registers too, for varargs */ - for (; reg < R11; reg++) { - NODE *r, *l; - l = bcon(0); - l->n_op = OREG; - l->n_lval = (passedargoff/SZCHAR); - l->n_rval = FPREG; - l->n_type = INT; - passedargoff += SZINT; - r = bcon(0); - r->n_op = REG; - r->n_rval = reg; - r->n_type = INT; - ecode(buildtree(ASSIGN, l, r)); - } -#endif - -#if 0 - printf("BFCODE end\n"); + /* profiling */ + if (pflag) { + NODE *p; + +#if defined(ELFABI) + + spname = lookup("_mcount", 0); + spname->stype = EXTERN; + p = buildtree(NAME, NIL, NIL); + p->n_sp->sclass = EXTERN; + p = clocal(p); + p = buildtree(ADDROF, p, NIL); + p = block(UCALL, p, NIL, INT, 0, MKSUE(INT)); + ecomp(funcode(p)); + + +#elif defined(MACHOABI) + + NODE *q; + int tmpnr; + + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0; + p = tempnode(0, INT, 0, MKSUE(INT)); + tmpnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(tmpnr, INT, 0, MKSUE(INT)); + + spname = lookup("mcount", 0); + spname->stype = EXTERN; + p = buildtree(NAME, NIL, NIL); + p->n_sp->sclass = EXTERN; + p = clocal(p); + p = buildtree(ADDROF, p, NIL); + p = block(CALL, p, q, INT, 0, MKSUE(INT)); + ecomp(funcode(p)); + #endif + } } +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int tempnr; + int ty; + +#ifdef USE_GOTNR + extern int gotnr; + gotnr = 0; +#endif + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + + ty = cftnsp->stype - FTN; + + q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue); + regno(q) = R3; + p = tempnode(0, INCREF(ty), 0, cftnsp->ssue); + tempnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(tempnr, INCREF(ty), 0, cftnsp->ssue); + q = buildtree(UMUL, q, NIL); + + p = tempnode(rvnr, INCREF(ty), 0, cftnsp->ssue); + p = buildtree(UMUL, p, NIL); + + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(rvnr, INCREF(ty), 0, cftnsp->ssue); + p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->ssue); + regno(p) = R3; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} /* * by now, the automatics and register variables are allocated @@ -193,9 +497,6 @@ bfcode(struct symtab **a, int n) void bccode() { -#if 0 - printf("BCCODE: autooff=%d, SZINT=%d\n", autooff, SZINT); -#endif SETOFF(autooff, SZINT); } @@ -207,58 +508,69 @@ struct stub nlplist; void ejobcode(int flag ) { -#if 0 - printf("EJOBCODE:\n"); -#endif +#if defined(MACHOABI) + /* + * iterate over the stublist and output the PIC stubs +` */ if (kflag) { - // iterate over the stublist and output the PIC stubs struct stub *p; DLIST_FOREACH(p, &stublist, link) { printf("\t.section __TEXT, __picsymbolstub1,symbol_stubs,pure_instructions,32\n"); printf("\t.align 5\n"); - printf("%s$stub:\n", p->name); - printf("\t.indirect_symbol %s\n", p->name); + printf("L%s$stub:\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", + exname(p->name)); printf("\tmflr r0\n"); - printf("\tbcl 20,31,L%s$stub$spb\n", p->name); - printf("L%s$stub$spb:\n", p->name); + printf("\tbcl 20,31,L%s$spb\n", p->name); + printf("L%s$spb:\n", p->name); printf("\tmflr r11\n"); - printf("\taddis r11,r11,ha16(L%s$lazy_ptr-L%s$stub$spb)\n", p->name, p->name); + printf("\taddis r11,r11,ha16(L%s$lazy_ptr-L%s$spb)\n", + p->name, p->name); printf("\tmtlr r0\n"); - printf("\tlwzu r12,lo16(L%s$lazy_ptr-L%s$stub$spb)(r11)\n", p->name, p->name); + printf("\tlwzu r12,lo16(L%s$lazy_ptr-L%s$spb)(r11)\n", + p->name, p->name); printf("\tmtctr r12\n"); printf("\tbctr\n"); printf("\t.lazy_symbol_pointer\n"); printf("L%s$lazy_ptr:\n", p->name); - printf("\t.indirect_symbol %s\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", + exname(p->name)); printf("\t.long dyld_stub_binding_helper\n"); printf("\t.subsections_via_symbols\n"); - } printf("\t.non_lazy_symbol_pointer\n"); DLIST_FOREACH(p, &nlplist, link) { printf("L%s$non_lazy_ptr:\n", p->name); - printf("\t.indirect_symbol %s\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", + exname(p->name)); printf("\t.long 0\n"); } - // memory leak here } +#endif + } void bjobcode() { -#if 0 - printf("BJOBCODE:\n"); -#endif - DLIST_INIT(&stublist, link); DLIST_INIT(&nlplist, link); } +#ifdef notdef /* * Print character t at position i in one string, until t == -1. * Locctr & label is already defined. @@ -292,6 +604,7 @@ bycode(int t, int i) } } } +#endif /* * return the alignment of field of type t @@ -299,7 +612,7 @@ bycode(int t, int i) int fldal(unsigned int t) { - uerror("illegal field type"); + uerror("fldal: illegal field type"); return(ALINT); } @@ -315,22 +628,14 @@ fldty(struct symtab *p) int mygenswitch(int num, TWORD type, struct swents **p, int n) { - return 0; -#if 0 - if (n == 0) { - if (p[0]->sval != 0) - branch(p[0]->sval); - return; + if (num > 10) { + genswitch_bintree(num, type, p, n); + return 1; } -#ifdef PCC_DEBUG - if (xdebug) { - int i; - for (i = 1; i <= n; i++) - printf("%d: %llu\n", i, p[i]->sval); - } -#endif + return 0; +#if 0 if (0) genswitch_table(num, p, n); if (0) @@ -339,46 +644,31 @@ mygenswitch(int num, TWORD type, struct swents **p, int n) #endif } -#if 0 -static void -genswitch_simple(int num, struct swents **p, int n) -{ - NODE *r; - int i; - - for (i = 1; i <= n; ++i) { - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); -} - -static void bintree_rec(int num, struct swents **p, int n, int s, int e); +static void bintree_rec(TWORD ty, int num, + struct swents **p, int n, int s, int e); static void -genswitch_bintree(int num, struct swents **p, int n) +genswitch_bintree(int num, TWORD ty, struct swents **p, int n) { int lab = getlab(); if (p[0]->slab == 0) p[0]->slab = lab; - bintree_rec(num, p, n, 1, n); + bintree_rec(ty, num, p, n, 1, n); plabel(lab); } static void -bintree_rec(int num, struct swents **p, int n, int s, int e) +bintree_rec(TWORD ty, int num, struct swents **p, int n, int s, int e) { NODE *r; int rlabel; int h; if (s == e) { - r = tempnode(num, INT, 0, MKSUE(INT)); + r = tempnode(num, ty, 0, MKSUE(ty)); r = buildtree(NE, r, bcon(p[s]->sval)); cbranch(buildtree(NOT, r, NIL), bcon(p[s]->slab)); branch(p[0]->slab); @@ -389,15 +679,16 @@ bintree_rec(int num, struct swents **p, int n, int s, int e) h = s + (e - s) / 2; - r = tempnode(num, INT, 0, MKSUE(INT)); + r = tempnode(num, ty, 0, MKSUE(ty)); r = buildtree(GT, r, bcon(p[h]->sval)); cbranch(r, bcon(rlabel)); - bintree_rec(num, p, n, s, h); + bintree_rec(ty, num, p, n, s, h); plabel(rlabel); - bintree_rec(num, p, n, h+1, e); + bintree_rec(ty, num, p, n, h+1, e); } +#if 0 static void genswitch_table(int num, struct swents **p, int n) @@ -422,7 +713,7 @@ genswitch_table(int num, struct swents **p, int n) r = tempnode(num, UNSIGNED, 0, MKSUE(UNSIGNED)); r = buildtree(MINUS, r, bcon(minval)); t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED)); - tval = t->n_lval; + tval = regno(t); r = buildtree(ASSIGN, t, r); ecomp(r); @@ -448,7 +739,7 @@ genswitch_table(int num, struct swents **p, int n) r = buildtree(ASSIGN, t, r); ecomp(r); - r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); r = buildtree(UMUL, r, NIL); t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR)); t->n_sp = strtbl; @@ -569,7 +860,7 @@ mrst_rec(int num, struct swents **p, int n, int *state, int lab) r = buildtree(RS, r, bcon(lowbit)); t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED)); - tval = t->n_lval; + tval = regno(t); r = buildtree(ASSIGN, t, r); ecomp(r); @@ -588,7 +879,7 @@ mrst_rec(int num, struct swents **p, int n, int *state, int lab) r = buildtree(ASSIGN, t, r); ecomp(r); - r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); r = buildtree(UMUL, r, NIL); t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR)); t->n_sp = strtbl; @@ -802,11 +1093,437 @@ mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *l #endif /* + * Straighten a chain of CM ops so that the CM nodes + * only appear on the left node. + * + * CM CM + * CM CM CM b + * x y a b CM a + * x y + * + * CM CM + * CM CM CM c + * CM z CM c CM b + * x y a b CM a + * CM z + * x y + */ +static NODE * +straighten(NODE *p) +{ + NODE *r = p->n_right; + + if (p->n_op != CM || r->n_op != CM) + return p; + + p->n_right = r->n_left; + r->n_left = straighten(p); + + return r; +} + +static NODE * +reverse1(NODE *p, NODE *a) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + a->n_right = r; + p->n_left = a; + + if (l->n_op == CM) { + return reverse1(l, p); + } else { + p->n_right = l; + return p; + } +} + +/* + * Reverse a chain of CM ops + */ +static NODE * +reverse(NODE *p) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + p->n_left = r; + + if (l->n_op == CM) + return reverse1(l, p); + + p->n_right = l; + + return p; +} + +/* push arg onto the stack */ +/* called by moveargs() */ +static NODE * +pusharg(NODE *p, int *regp) +{ + NODE *q; + int sz; + int off; + + /* convert to register size, if smaller */ + sz = tsize(p->n_type, p->n_df, p->n_sue); + if (sz < SZINT) + p = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); + + q = block(REG, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_sue); + regno(q) = SPREG; + + off = ARGINIT/SZCHAR + 4 * (*regp - R3); + q = block(PLUS, q, bcon(off), INT, 0, MKSUE(INT)); + q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_sue); + (*regp) += szty(p->n_type); + + return buildtree(ASSIGN, q, p); +} + +/* setup call stack with 32-bit argument */ +/* 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_sue); + regno(q) = reg++; + q = buildtree(ASSIGN, q, p); + + *regp = reg; + return q; +} + +/* setup call stack with 64-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_64bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q, *r; + +#if ALLONGLONG == 64 + /* alignment */ + ++reg; + reg &= ~1; +#endif + + if (reg > R10) { + *regp = reg; + q = pusharg(p, regp); + } else if (reg == R10) { + /* half in and half out of the registers */ + r = tcopy(p); + if (!features(FEATURE_BIGENDIAN)) { + q = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); + q = movearg_32bit(q, regp); /* little-endian */ + r = buildtree(RS, r, bcon(32)); + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + r = pusharg(r, regp); /* little-endian */ + } else { + q = buildtree(RS, p, bcon(32)); + q = block(SCONV, q, NIL, INT, 0, MKSUE(INT)); + q = movearg_32bit(q, regp); /* big-endian */ + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + r = pusharg(r, regp); /* big-endian */ + } + q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_sue)); + } else { + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + regno(q) = R3R4 + (reg - R3); + q = buildtree(ASSIGN, q, p); + *regp = reg + 2; + } + + return q; +} + +/* setup call stack with float argument */ +/* called from moveargs() */ +static NODE * +movearg_float(NODE *p, int *fregp, int *regp) +{ +#if defined(MACHOABI) + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; +#endif + + p = movearg_32bit(p, fregp); + + /* + * On OS/X, floats are passed in the floating-point registers + * and in the general registers for compatibily with libraries + * compiled to handle soft-float. + */ + +#if defined(MACHOABI) + + if (xtemps) { + /* bounce into TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-4), INT, 0, MKSUE(INT)); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT)); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-4), INT, 0, MKSUE(INT)); + r = block(UMUL, r, NIL, INT, 0, MKSUE(INT)); + q = tempnode(0, INT, 0, MKSUE(INT)); + 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_sue); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, INT, 0, MKSUE(INT)); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = (*regp)++; + p = buildtree(ASSIGN, q, r); + +#endif + return p; + +} + +/* setup call stack with float/double argument */ +/* called from moveargs() */ +static NODE * +movearg_double(NODE *p, int *fregp, int *regp) +{ +#if defined(MACHOABI) + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; +#endif + + /* this does the move to a single register for us */ + p = movearg_32bit(p, fregp); + + /* + * On OS/X, doubles are passed in the floating-point registers + * and in the general registers for compatibily with libraries + * compiled to handle soft-float. + */ + +#if defined(MACHOABI) + + if (xtemps) { + /* bounce on TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_sue); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+LONGLONG, 0, MKSUE(LONGLONG)); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, MKSUE(LONGLONG)); + r = block(UMUL, r, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + q = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG)); + 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_sue); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, LONGLONG, 0, MKSUE(LONGLONG)); + q = block(REG, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + regno(q) = R3R4 - R3 + (*regp); + p = buildtree(ASSIGN, q, r); + + (*regp) += 2; + +#endif + + return p; +} + +/* setup call stack with a structure */ +/* called from moveargs() */ +static NODE * +movearg_struct(NODE *p, int *regp) +{ + int reg = *regp; + NODE *l, *q, *t, *r; + int tmpnr; + int navail; + int num; + int sz; + int ty; + int i; + + assert(p->n_op == STARG); + + navail = NARGREGS - (reg - R3); + navail = navail < 0 ? 0 : navail; + sz = tsize(p->n_type, p->n_df, p->n_sue) / SZINT; + num = sz > navail ? navail : sz; + + /* remove STARG node */ + l = p->n_left; + nfree(p); + ty = l->n_type; + + /* + * put it into a TEMP, rather than tcopy(), since the tree + * in p may have side-affects + */ + t = tempnode(0, ty, l->n_df, l->n_sue); + tmpnr = regno(t); + q = buildtree(ASSIGN, t, l); + + /* copy structure into registers */ + for (i = 0; i < num; i++) { + t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT)); + t = buildtree(UMUL, t, NIL); + + r = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(r) = reg++; + r = buildtree(ASSIGN, r, t); + + q = block(CM, q, r, INT, 0, MKSUE(INT)); + } + + /* put the rest of the structure on the stack */ + for (i = num; i < sz; i++) { + t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT)); + t = buildtree(UMUL, t, NIL); + r = pusharg(t, ®); + q = block(CM, q, r, INT, 0, MKSUE(INT)); + } + + q = reverse(q); + + *regp = reg; + return q; +} + + +static NODE * +moveargs(NODE *p, int *regp, int *fregp) +{ + NODE *r, **rp; + int reg, freg; + + if (p->n_op == CM) { + p->n_left = moveargs(p->n_left, regp, fregp); + r = p->n_right; + rp = &p->n_right; + } else { + r = p; + rp = &p; + } + + reg = *regp; + freg = *fregp; + +#define ISFLOAT(p) (p->n_type == FLOAT || \ + p->n_type == DOUBLE || \ + p->n_type == LDOUBLE) + + if (reg > R10 && r->n_op != STARG) { + *rp = pusharg(r, regp); + } else if (r->n_op == STARG) { + *rp = movearg_struct(r, regp); + } else if (DEUNSIGN(r->n_type) == LONGLONG) { + *rp = movearg_64bit(r, regp); + } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + *rp = movearg_double(r, fregp, regp); + else + *rp = movearg_64bit(r, regp); + } else if (r->n_type == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + *rp = movearg_float(r, fregp, regp); + else + *rp = movearg_32bit(r, regp); + } else { + *rp = movearg_32bit(r, regp); + } + + return straighten(p); +} + +/* + * Fixup arguments to pass pointer-to-struct as first argument. + * + * called from funcode(). + */ +static NODE * +retstruct(NODE *p) +{ + NODE *l, *r, *t, *q; + TWORD ty; + + l = p->n_left; + r = p->n_right; + + ty = DECREF(l->n_type) - FTN; + +// assert(tsize(ty, l->n_df, l->n_sue) == SZINT); + + /* structure assign */ + q = tempnode(0, ty, l->n_df, l->n_sue); + q = buildtree(ADDROF, q, NIL); + + /* insert hidden assignment at beginning of list */ + if (r->n_op != CM) { + p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_sue); + } else { + for (t = r; t->n_left->n_op == CM; t = t->n_left) + ; + t->n_left = block(CM, q, t->n_left, INCREF(ty), + l->n_df, l->n_sue); + } + + return p; +} + +/* * Called with a function call with arguments as argument. * This is done early in buildtree() and only done once. */ NODE * funcode(NODE *p) { + int regnum = R3; + int fregnum = F1; + + if (p->n_type == STRTY+FTN || p->n_type == UNIONTY+FTN) + p = retstruct(p); + + p->n_right = moveargs(p->n_right, ®num, &fregnum); + + if (p->n_right == NULL) + p->n_op += (UCALL - CALL); + return p; } diff --git a/usr.bin/pcc/powerpc/local.c b/usr.bin/pcc/powerpc/local.c index 76a90a122a3..d6636d98443 100644 --- a/usr.bin/pcc/powerpc/local.c +++ b/usr.bin/pcc/powerpc/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.5 2007/12/22 14:05:04 stefan Exp $ */ +/* $OpenBSD: local.c,v 1.6 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -27,9 +27,12 @@ */ #include <assert.h> - #include "pass1.h" +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +#define SNOUNDERSCORE SLOCAL1 + extern int kflag; static @@ -37,103 +40,206 @@ void simmod(NODE *p); /* this file contains code which is dependent on the target machine */ -/* don't permit CALLs to be arguments to other CALLs (nest CALLs) */ +#if defined(MACHOABI) + +/* + * Keep track of PIC stubs. + */ + +void +addstub(struct stub *list, char *name) +{ + struct stub *s; + + DLIST_FOREACH(s, list, link) { + if (strcmp(s->name, name) == 0) + return; + } + + if ((s = permalloc(sizeof(struct stub))) == NULL) + cerror("addstub: malloc"); + if ((s->name = strdup(name)) == NULL) + cerror("addstub: strdup"); + DLIST_INSERT_BEFORE(list, s, link); +} + +#endif + + +/* + * Make a symtab entry for PIC use. + */ +static struct symtab * +picsymtab(char *p, char *s, char *s2) +{ + struct symtab *sp = IALLOC(sizeof(struct symtab)); + size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; + + sp->sname = sp->soname = IALLOC(len); + strlcpy(sp->soname, p, len); + strlcat(sp->soname, s, len); + strlcat(sp->soname, s2, len); + sp->sclass = EXTERN; + sp->sflags = sp->slevel = 0; + return sp; +} + +int gotnr; /* tempnum for GOT register */ + +/* + * Create a reference for an extern variable. + */ static NODE * -emitinnercall(NODE *r) +picext(NODE *p) { - NODE *tmp1, *tmp2; + NODE *q; + struct symtab *sp; -#ifdef PCC_DEBUG - if (xdebug) { - printf("clocal::emitinnercall():\n"); - fwalk(r, eprint, 0); + if (strncmp(p->n_sp->soname, "__builtin", 9) == 0) + return p; + +#if defined(ELFABI) + + sp = picsymtab("", p->n_sp->soname, "@got(31)"); + q = xbcon(0, sp, PTR+VOID); + q = block(UMUL, q, 0, PTR+VOID, 0, MKSUE(VOID)); + +#elif defined(MACHOABI) + + char buf2[64]; + NODE *r; + + if (p->n_sp->sclass == EXTDEF) { + snprintf(buf2, 64, "-L%s$pb", cftnsp->soname); + sp = picsymtab("", exname(p->n_sp->soname), buf2); + } else { + snprintf(buf2, 64, "$non_lazy_ptr-L%s$pb", cftnsp->soname); + sp = picsymtab("L", p->n_sp->soname, buf2); + addstub(&nlplist, p->n_sp->soname); } +#if USE_GOTNR + q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID)); +#else + q = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID)); + regno(q) = GOTREG; +#endif + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + if (p->n_sp->sclass != EXTDEF) + q = block(UMUL, q, 0, PTR+VOID, 0, MKSUE(VOID)); + #endif - tmp1 = tempnode(0, r->n_type, r->n_df, r->n_sue); - tmp2 = tempnode(tmp1->n_lval, r->n_type, r->n_df, r->n_sue); - ecode(buildtree(ASSIGN, tmp1, r)); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); + q->n_sp = p->n_sp; /* for init */ + nfree(p); - return tmp2; + return q; } - -static void -breaknestedcalls(NODE *p) + +/* + * Create a reference for a static variable + */ + +static NODE * +picstatic(NODE *p) { + NODE *q; + struct symtab *sp; + +#if defined(ELFABI) + + if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) { + char buf[64]; + snprintf(buf, 64, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf, "@got(31)"); + sp->sflags |= SNOUNDERSCORE; + } else { + sp = picsymtab("", p->n_sp->soname, "@got(31)"); + } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + q = xbcon(0, sp, PTR+VOID); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); + q->n_sp = p->n_sp; + nfree(p); + +#elif defined(MACHOABI) + + char buf2[64]; NODE *r; - for (r = p->n_right; r->n_op == CM; r = r->n_left) { - if (r->n_right->n_op == CALL) - r->n_right = emitinnercall(r->n_right); - if (r->n_left->n_op == CALL) - r->n_left = emitinnercall(r->n_left); - } + snprintf(buf2, 64, "-L%s$pb", cftnsp->soname); -#ifdef PCC_DEBUG - if (xdebug) { - printf("clocal::breaknestedcalls(): exiting with tree:\n"); - fwalk(p, eprint, 0); + if (p->n_sp->slevel > 0 || p->n_sp->sclass == ILABEL) { + char buf1[64]; + snprintf(buf1, 64, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf1, buf2); + sp->sflags |= SNOUNDERSCORE; + } else { + sp = picsymtab("", exname(p->n_sp->soname), buf2); } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; +#if USE_GOTNR + q = tempnode(gotnr, PTR+VOID, 0, MKSUE(VOID)); +#else + q = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(VOID)); + regno(q) = GOTREG; +#endif + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_sue); + q->n_sp = p->n_sp; + nfree(p); + #endif + + return q; } -static void -fixupfuncargs(NODE *r, int *reg) +static NODE * +convert_ulltof(NODE *p) { -#ifdef PCC_DEBUG - if (xdebug) - printf("fixupfuncargs(): r=%p\n", r); -#endif + NODE *q, *r, *l, *t; + int ty; + int tmpnr; - if (r->n_op == CM) { - /* recurse to the bottom of the tree */ - fixupfuncargs(r->n_left, reg); + ty = p->n_type; + l = p->n_left; + nfree(p); - if (r->n_right->n_op == STARG) { - assert(0); - } + q = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG)); + tmpnr = regno(q); + t = buildtree(ASSIGN, q, l); + ecomp(t); - r->n_right = block(ASSIGN, NIL, r->n_right, - r->n_right->n_type, r->n_right->n_df, - r->n_right->n_sue); - r->n_right->n_left = block(REG, NIL, NIL, r->n_right->n_type, 0, MKSUE(INT)); + //q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG)); + //q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + q = tempnode(tmpnr, LONGLONG, 0, MKSUE(LONGLONG)); + r = block(SCONV, q, NIL, ty, 0, MKSUE(ty)); - if (r->n_right->n_type == ULONGLONG || r->n_right->n_type == LONGLONG) { - r->n_right->n_left->n_rval = R3R4 + (*reg) - R3; - (*reg) += 2; - } else { - r->n_right->n_left->n_rval = (*reg); - (*reg)++; - } + q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG)); + q = block(RS, q, bcon(1), ULONGLONG, 0, MKSUE(ULONGLONG)); + q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + q = block(SCONV, q, NIL, ty, 0, MKSUE(ty)); + t = block(FCON, NIL, NIL, ty, 0, MKSUE(ty)); + t->n_dcon = 2; + l = block(MUL, q, t, ty, 0, MKSUE(ty)); - } else { + r = buildtree(COLON, l, r); - if (r->n_op == STARG) { - assert(0); -#if 0 - copystructtostack(r->); - *r = *(r->n_left) - nfree(r->n_left); - return; -#endif - } + q = tempnode(tmpnr, ULONGLONG, 0, MKSUE(ULONGLONG)); + q = block(SCONV, q, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + l = block(LE, q, xbcon(0, NULL, LONGLONG), INT, 0, MKSUE(INT)); + + return clocal(buildtree(QUEST, l, r)); - NODE *l = talloc(); - *l = *r; - r->n_op = ASSIGN; - r->n_left = block(REG, NIL, NIL, l->n_type, 0, MKSUE(INT)); - r->n_right = l; - if (r->n_right->n_type == ULONGLONG || r->n_right->n_type == LONGLONG) { - r->n_left->n_rval = R3R4 + (*reg) - R3; - (*reg) += 2; - } else { - r->n_left->n_rval = (*reg); - (*reg)++; - } - } } + /* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. @@ -154,6 +260,8 @@ clocal(NODE *p) int o; int m; TWORD t; + int isptrvoid = 0; + int tmpnr; #ifdef PCC_DEBUG if (xdebug) { @@ -171,48 +279,21 @@ clocal(NODE *p) } #endif - if (kflag && blevel > 0 && p->n_left->n_op == NAME) { - -#if 0 - printf("sclass=%d, squal=%d, slevel=%d: ", p->n_left->n_sp->sclass, p->n_left->n_sp->squal, p->n_left->n_sp->slevel); - tprint(stdout, p->n_left->n_type, p->n_left->n_qual); - printf("\n"); -#endif - - TWORD t = DECREF(p->n_type); - - if (!ISFTN(t)) { - - int isextern = (p->n_sp && p->n_sp->sclass == EXTERN); - int off = 0; - - if (isextern) { - off = p->n_lval; - p->n_lval = 0; - } - - r = talloc(); - *r = *p; - - /* cast to pointer-to-char before adding offset */ - l = block(REG, NIL, NIL, INT, p->n_df, p->n_sue); - l->n_lval = 0; - l->n_rval = R31; - - r = block(SCONV, r, NIL, INCREF(UCHAR), p->n_df,p->n_sue); - r = block(PLUS, l, r, r->n_type, r->n_df, r->n_sue); - - if (off) - r = block(PLUS, r, bcon(off), r->n_type, r->n_df, r->n_sue); - - p->n_op = SCONV; - p->n_lval = 0; - p->n_left = r; - p->n_rval = 0; - p->n_right = 0; - } - - } + if (kflag == 0 || blevel == 0) + break; + /* char arrays may end up here */ + l = p->n_left; + if (l->n_op != NAME || + (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) + break; + l = p; + p = picstatic(p->n_left); + nfree(l); + if (p->n_op != UMUL) + cerror("ADDROF error"); + l = p; + p = p->n_left; + nfree(l); break; case NAME: @@ -230,82 +311,74 @@ clocal(NODE *p) p = stref(block(STREF, r, p, 0, 0, 0)); break; + case USTATIC: + if (kflag == 0) + break; + /* FALLTHROUGH */ + + case STATIC: + if (kflag == 0) { + if (q->slevel == 0) + break; + p->n_lval = 0; + } else if (blevel > 0) { + p = picstatic(p); + } + break; + case REGISTER: p->n_op = REG; p->n_lval = 0; p->n_rval = q->soffset; break; - case STATIC: - if (q->slevel > 0) { - p->n_lval = 0; - p->n_sp = q; - } - /* FALLTHROUGH */ - default: - if (kflag && blevel > 0 && !ISFTN(p->n_type)) { - TWORD t = p->n_type; - int isextern = p->n_sp->sclass == EXTERN; - int off = 0; - - if (isextern) - t = INCREF(t); - - l = block(REG, NIL, NIL, INCREF(t), p->n_df, p->n_sue); - l->n_lval = 0; - l->n_rval = R31; - - p->n_op = ICON; - p->n_type = INCREF(t); - if (isextern) { - off = p->n_lval; - p->n_lval = 0; - } - - p = block(PLUS, l, p, INCREF(t), p->n_df, p->n_sue); + case EXTERN: + case EXTDEF: + if (kflag == 0) + break; + if (blevel > 0) + p = picext(p); + break; - if (isextern) { - p = block(UMUL, p, NIL, t, p->n_df, p->n_sue); - if (off) - p = block(PLUS, p, bcon(off), t, p->n_df, p->n_sue); - t = DECREF(t); - } - p = block(UMUL, p, NIL, t, p->n_df, p->n_sue); - } + case ILABEL: + if (kflag && blevel > 0) + p = picstatic(p); + break; } break; - case STCALL: - case CALL: - - breaknestedcalls(p); - - /* Fix function call arguments. */ - /* move everything into the registers */ - { - int reg = R3; - fixupfuncargs(p->n_right, ®); - } - /* FALLTHOUGH */ - -#if 0 case UCALL: - - /* check if it's an indirect call and offset with R30 */ - if (p->n_left->n_op == REG) { - l = block(REG, NIL, NIL, INT, p->n_df, MKSUE(INT)); - l->n_lval = 0; - l->n_rval = R31; - p->n_left = block(PLUS, p->n_left, l, p->n_type, p->n_df, p->n_sue); - } -#endif - -#if 0 - r = tempnode(0, p->n_type, p->n_df, p->n_sue); - ecomp(buildtree(ASSIGN, r, p)); - return r; + case CALL: + case USTCALL: + case STCALL: + if (p->n_type == VOID) + break; + /* + * if the function returns void*, ecode() invokes + * delvoid() to convert it to uchar*. + * We just let this happen on the ASSIGN to the temp, + * and cast the pointer back to void* on access + * from the temp. + */ + if (p->n_type == PTR+VOID) + isptrvoid = 1; + r = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(r); + r = buildtree(ASSIGN, r, p); + + p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); + if (isptrvoid) { + p = block(PCONV, p, NIL, PTR+VOID, + p->n_df, MKSUE(PTR+VOID)); + } +#if 1 + p = buildtree(COMOP, r, p); +#else + /* XXX this doesn't work if the call is already in a COMOP */ + r = clocal(r); + ecomp(r); #endif - break; + break; case CBRANCH: l = p->n_left; @@ -337,8 +410,7 @@ clocal(NODE *p) l->n_lval = (unsigned)l->n_lval; goto delp; } - if (l->n_type < INT || l->n_type == LONGLONG || - l->n_type == ULONGLONG) { + if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) { /* float etc? */ p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, MKSUE(UNSIGNED)); @@ -373,9 +445,6 @@ clocal(NODE *p) return l; } - if (xdebug) - printf("SCONV 1\n"); - if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && btdims[p->n_type].suesize == btdims[l->n_type].suesize) { if (p->n_type != FLOAT && p->n_type != DOUBLE && @@ -397,6 +466,15 @@ clocal(NODE *p) return l; } + /* + * if converting ULONGLONG to FLOAT/(L)DOUBLE, + * replace ___floatunsdidf() with ___floatdidf() + */ + if (l->n_type == ULONGLONG && p->n_type >= FLOAT && + p->n_type <= LDOUBLE) { + return convert_ulltof(p); + } + o = l->n_op; m = p->n_type; @@ -449,20 +527,36 @@ clocal(NODE *p) l->n_sue = MKSUE(m); nfree(p); return l; + } else if (o == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return clocal(l); } if (DEUNSIGN(p->n_type) == SHORT && DEUNSIGN(l->n_type) == SHORT) { nfree(p); p = l; } - if ((p->n_type == CHAR || p->n_type == UCHAR || - p->n_type == SHORT || p->n_type == USHORT) && + if ((DEUNSIGN(p->n_type) == CHAR || + DEUNSIGN(p->n_type) == SHORT) && (l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)) { p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); p->n_left->n_type = INT; return p; } + if ((DEUNSIGN(l->n_type) == CHAR || + DEUNSIGN(l->n_type) == SHORT) && + (p->n_type == FLOAT || p->n_type == DOUBLE || + p->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_type = INT; + return p; + } break; case MOD: @@ -485,6 +579,16 @@ clocal(NODE *p) nfree(p); return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + case STNAME: + if ((q = p->n_sp) == NULL) + return p; + if (q->sclass != STNAME) + return p; + t = p->n_type; + p = block(ADDROF, p, NIL, INCREF(t), p->n_df, p->n_sue); + p = block(UMUL, p, NIL, t, p->n_df, p->n_sue); + break; + case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; @@ -496,16 +600,14 @@ clocal(NODE *p) case LS: case RS: - /* unless longlong, where it must be int */ if (p->n_right->n_op == ICON) break; /* do not do anything */ - if (p->n_type == LONGLONG || p->n_type == ULONGLONG) { - if (p->n_right->n_type != INT) - p->n_right = block(SCONV, p->n_right, NIL, - INT, 0, MKSUE(INT)); - } + if (DEUNSIGN(p->n_right->n_type) == INT) + break; + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT)); break; } + #ifdef PCC_DEBUG if (xdebug) { printf("clocal end: %p\n", p); @@ -515,9 +617,114 @@ clocal(NODE *p) return(p); } +/* + * Change CALL references to either direct (static) or PLT. + */ +static void +fixnames(NODE *p) +{ + struct symtab *sp; + struct suedef *sue; + NODE *q; + char *c; + int isu; + + if ((cdope(p->n_op) & CALLFLG) == 0) + return; + + isu = 0; + q = p->n_left; + sue = q->n_sue; + if (q->n_op == UMUL) + q = q->n_left, isu = 1; + +#if defined(ELFABI) + + if (q->n_op == ICON) { + sp = q->n_sp; + +#elif defined(MACHOABI) + +#ifdef USE_GOTNR + if (q->n_op == PLUS && q->n_left->n_op == TEMP && +#else + if (q->n_op == PLUS && q->n_left->n_op == REG && +#endif + q->n_right->n_op == ICON) { + sp = q->n_right->n_sp; +#endif + + if (sp == NULL) + return; /* nothing to do */ + if (sp->sclass == STATIC && !ISFTN(sp->stype)) + return; /* function pointer */ + + if (sp->sclass != STATIC && sp->sclass != EXTERN && + sp->sclass != EXTDEF) + cerror("fixnames"); + +#if defined(ELFABI) + + if ((c = strstr(sp->soname, "@got(31)")) == NULL) + cerror("fixnames2"); + if (isu) { + strcpy(c, "@plt"); + } else + *c = 0; + +#elif defined(MACHOABI) + + if ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL && + (c = strstr(sp->soname, "-L")) == NULL) + cerror("fixnames2"); + if (isu) { + *c = 0; + addstub(&stublist, sp->soname+1); + strcpy(c, "$stub"); + } else + *c = 0; + + nfree(q->n_left); + q = q->n_right; + if (isu) + nfree(p->n_left->n_left); + nfree(p->n_left); + p->n_left = q; + q->n_sue = sue; + +#endif + } +} + void myp2tree(NODE *p) { + int o = p->n_op; + struct symtab *sp; + + if (kflag) + walkf(p, fixnames); + if (o != FCON) + return; + + /* Write float constants to memory */ + /* Should be voluntary per architecture */ + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; } /*ARGSUSED*/ @@ -546,8 +753,6 @@ cendarg() int cisreg(TWORD t) { - if (t == FLOAT || t == DOUBLE || t == LDOUBLE) - return 0; /* not yet */ return 1; } @@ -556,8 +761,6 @@ cisreg(TWORD t) * being added to a pointer of type t, in order to be off bits offset * into a structure * t, d, and s are the type, dimension offset, and sizeoffset - * For pdp10, return the type-specific index number which calculation - * is based on its size. For example, short a[3] would return 3. * Be careful about only handling first-level pointers, the following * indirections must be fullword. */ @@ -578,71 +781,85 @@ offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) } /* - * Allocate off bits on the stack. p is a tree that when evaluated - * is the multiply count for off, t is a storeable node where to write - * the allocated address. + * Allocate bits on the stack. + * 'off' is the number of bits to allocate + * 'p' is a tree that when evaluated is the multiply count for 'off' + * 't' is a storeable node where to write the allocated address */ void spalloc(NODE *t, NODE *p, OFFSZ off) { -#if 0 - NODE *sp; -#endif - - p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ - - assert(0); -#if 0 - /* sub the size from sp */ - sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); - sp->n_lval = 0; - sp->n_rval = STKREG; - ecomp(buildtree(MINUSEQ, sp, p)); - - /* save the address of sp */ - sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); - sp->n_lval = 0; - sp->n_rval = STKREG; - t->n_type = sp->n_type; - ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ -#endif - -} - -#if 0 -/* - * Print out an integer constant of size size. - * can only be sizes <= SZINT. - */ -void -indata(CONSZ val, int size) -{ - switch (size) { - case SZCHAR: - printf("\t.byte %d\n", (int)val & 0xff); - break; - case SZSHORT: - printf("\t.word %d\n", (int)val & 0xffff); - break; - case SZINT: - printf("\t.long %d\n", (int)val & 0xffffffff); - break; - default: - cerror("indata"); - } + NODE *q, *r; + int nbytes = off / SZCHAR; + int stacksize = 24+40; /* this should be p2stacksize */ + + /* + * After we subtract the requisite bytes + * off the stack, we need to step back over + * the 40 bytes for the arguments registers + * *and* any other parameters which will get + * saved to the stack. Unfortunately, we + * don't have that information in pass1 and + * the parameters will stomp on the allocated + * space for alloca(). + * + * No fix yet. + */ + werror("parameters may stomp on alloca()"); + + /* compute size */ + p = buildtree(MUL, p, bcon(nbytes)); + p = buildtree(PLUS, p, bcon(ALSTACK/SZCHAR)); + + /* load the top-of-stack */ + q = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT)); + regno(q) = SPREG; + q = block(UMUL, q, NIL, INT, 0, MKSUE(INT)); + + /* save old top-of-stack value to new top-of-stack position */ + r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT)); + regno(r) = SPREG; + r = block(MINUSEQ, r, p, INT, 0, MKSUE(INT)); + r = block(UMUL, r, NIL, INT, 0, MKSUE(INT)); + ecomp(buildtree(ASSIGN, r, q)); + + r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT)); + regno(r) = SPREG; + + /* skip over the arguments space and align to 16 bytes */ + r = block(PLUS, r, bcon(stacksize + 15), INT, 0, MKSUE(INT)); + r = block(RS, r, bcon(4), INT, 0, MKSUE(INT)); + r = block(LS, r, bcon(4), INT, 0, MKSUE(INT)); + + t->n_type = p->n_type; + ecomp(buildtree(ASSIGN, t, r)); } -#endif -#if 0 /* * Print out a string of characters. - * Assume that the assembler understands C-style escape - * sequences. Location is already set. + * Unfortunately, this code assumes that the assembler understands + * C-style escape sequences. (which it doesn't!) + * Location is already set. */ void -instring(char *str) +instring(struct symtab *sp) { - char *s; + char *s, *str = sp->sname; + +#if defined(ELFABI) + + defloc(sp); + +#elif defined(MACHOABI) + + extern int lastloc; + if (lastloc != STRNG) + printf(" .cstring\n"); + lastloc = STRNG; + printf(" .p2align 1\n"); + printf(LABFMT ":\n", sp->soffset); + +#endif /* be kind to assemblers and avoid long strings */ printf("\t.ascii \""); @@ -659,7 +876,27 @@ instring(char *str) fwrite(str, 1, s - str, stdout); printf("\\0\"\n"); } -#endif + +/* + * Print out a wide string by calling ninval(). + */ +void +inwstring(struct symtab *sp) +{ + char *s = sp->sname; + NODE *p; + + defloc(sp); + p = bcon(0); + do { + if (*s++ == '\\') + p->n_lval = esccon(&s); + else + p->n_lval = (unsigned char)s[-1]; + ninval(0, (MKSUE(WCHAR_TYPE))->suesize, p); + } while (s[-1] != 0); + nfree(p); +} static int inbits, inval; @@ -673,6 +910,9 @@ zbits(OFFSZ off, int fsz) if (idebug) printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + +#if 0 + /* little-endian */ if ((m = (inbits % SZCHAR))) { m = SZCHAR - m; if (fsz < m) { @@ -684,6 +924,20 @@ zbits(OFFSZ off, int fsz) inval = inbits = 0; } } +#endif + /* big-endian */ + if (inbits) { + m = SZCHAR - inbits; + if (fsz < m) { + inbits += fsz; + inval <<= fsz; + } else { + printf("\t.byte %d\n", inval << m); + fsz -= m; + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { printf("\t.space %d\n", fsz/SZCHAR); fsz -= (fsz/SZCHAR) * SZCHAR; @@ -703,7 +957,11 @@ infld(CONSZ off, int fsz, CONSZ val) if (idebug) printf("infld off %lld, fsz %d, val %lld inbits %d\n", off, fsz, val, inbits); + val &= (1 << fsz)-1; + +#if 0 + /* little-endian */ while (fsz + inbits >= SZCHAR) { inval |= (val << inbits); printf("\t.byte %d\n", inval & 255); @@ -715,6 +973,17 @@ infld(CONSZ off, int fsz, CONSZ val) inval |= (val << inbits); inbits += fsz; } +#endif + + /* big-endian */ + inval <<= fsz; + inval |= val; + inbits += fsz; + while (inbits >= SZCHAR) { + int pval = inval >> (inbits - SZCHAR); + printf("\t.byte %d\n", pval & 255); + inbits -= SZCHAR; + } } /* @@ -728,6 +997,7 @@ ninval(CONSZ off, int fsz, NODE *p) { union { float f; double d; long double l; int i[3]; } u; struct symtab *q; + char *c; TWORD t; int i; @@ -735,8 +1005,39 @@ ninval(CONSZ off, int fsz, NODE *p) if (t > BTMASK) t = INT; /* pointer */ + while (p->n_op == SCONV || p->n_op == PCONV) { + NODE *l = p->n_left; + l->n_type = p->n_type; + p = l; + } + + if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) { + if (p->n_op == UMUL) + p = p->n_left; + p = p->n_right; + q = p->n_sp; + +#if defined(ELFABI) + + if ((c = strstr(q->soname, "@got(31)")) != NULL) + *c = 0; /* ignore GOT ref here */ + +#elif defined(MACHOABI) + + if ((c = strstr(q->soname, "$non_lazy_ptr")) != NULL) { + q->soname++; /* skip "L" */ + *c = 0; /* ignore GOT ref here */ + } + else if ((c = strstr(q->soname, "-L")) != NULL) + *c = 0; /* ignore GOT ref here */ + +#endif + + } + if (p->n_op != ICON && p->n_op != FCON) - cerror("ninval: init node not constant"); + cerror("ninval: init node not constant: node %p [%s]", + p, cftnsp->soname); if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) uerror("element not constant"); @@ -744,28 +1045,46 @@ ninval(CONSZ off, int fsz, NODE *p) switch (t) { case LONGLONG: case ULONGLONG: +#if 0 + /* little-endian */ i = (p->n_lval >> 32); p->n_lval &= 0xffffffff; p->n_type = INT; ninval(off, 32, p); p->n_lval = i; ninval(off+32, 32, p); +#endif + /* big-endian */ + i = (p->n_lval & 0xffffffff); + p->n_lval >>= 32; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + break; case INT: case UNSIGNED: - printf("\t.long 0x%x", (int)p->n_lval); + printf("\t.long %d", (int)p->n_lval); if ((q = p->n_sp) != NULL) { if ((q->sclass == STATIC && q->slevel > 0) || q->sclass == ILABEL) { printf("+" LABFMT, q->soffset); - } else - printf("+%s", exname(q->sname)); + } else { + +#if defined(MACHOABI) + if ((q->sflags & SNOUNDERSCORE) != 0) + printf("+%s", q->soname); + else +#endif + printf("+%s", exname(q->soname)); + } } printf("\n"); break; case SHORT: case USHORT: - printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + printf("\t.short %d\n", (int)p->n_lval & 0xffff); break; case BOOL: if (p->n_lval > 1) @@ -778,62 +1097,36 @@ ninval(CONSZ off, int fsz, NODE *p) case LDOUBLE: u.i[2] = 0; u.l = (long double)p->n_dcon; - printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); +#if 0 + /* little-endian */ + printf("\t.long 0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); +#endif + /* big-endian */ + printf("\t.long 0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); break; case DOUBLE: u.d = (double)p->n_dcon; - printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); + printf("\t.long 0x%x\n\t.long 0x%x\n", u.i[0], u.i[1]); break; case FLOAT: u.f = (float)p->n_dcon; - printf("\t.long\t0x%x\n", u.i[0]); + printf("\t.long 0x%x\n", u.i[0]); break; default: cerror("ninval"); } } -#if 0 -/* - * print out an integer. - */ -void -inval(CONSZ word) -{ - word &= 0xffffffff; - printf(" .long 0x%llx\n", word); -} - -/* output code to initialize a floating point value */ -/* the proper alignment has been obtained */ -void -finval(NODE *p) -{ - union { float f; double d; long double l; int i[3]; } u; - - switch (p->n_type) { - case LDOUBLE: - u.i[2] = 0; - u.l = (long double)p->n_dcon; - printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); - break; - case DOUBLE: - u.d = (double)p->n_dcon; - printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); - break; - case FLOAT: - u.f = (float)p->n_dcon; - printf("\t.long\t0x%x\n", u.i[0]); - break; - } -} -#endif - /* make a name look like an external name in the local machine */ char * exname(char *p) { -#ifndef ELFABI +#if defined(ELFABI) + + return (p == NULL ? "" : p); + +#elif defined(MACHOABI) + #define NCHNAM 256 static char text[NCHNAM+1]; int i; @@ -849,8 +1142,7 @@ exname(char *p) text[NCHNAM] = '\0'; /* truncate */ return (text); -#else - return (p == NULL ? "" : p); + #endif } @@ -892,17 +1184,30 @@ extdec(struct symtab *q) /* make a common declaration for id, if reasonable */ void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + printf("\t.%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,%d\n", exname(sp->soname), off); + else + printf(LABFMT ",%d\n", sp->soffset, off); +} + + +#ifdef notdef +/* make a common declaration for id, if reasonable */ +void commdec(struct symtab *q) { int off; off = tsize(q->stype, q->sdf, q->ssue); off = (off+(SZCHAR-1))/SZCHAR; -#ifdef GCC_COMPAT - printf(" .comm %s,0%o\n", exname(gcc_findname(q)), off); -#else - printf(" .comm %s,0%o\n", exname(q->sname), off); -#endif + printf("\t.comm %s,0%o\n", exname(q->soname), off); } /* make a local common declaration for id, if reasonable */ @@ -914,13 +1219,9 @@ lcommdec(struct symtab *q) off = tsize(q->stype, q->sdf, q->ssue); off = (off+(SZCHAR-1))/SZCHAR; if (q->slevel == 0) -#ifdef GCC_COMPAT - printf(" .lcomm %s,0%o\n", exname(gcc_findname(q)), off); -#else - printf(" .lcomm %s,0%o\n", exname(q->sname), off); -#endif + printf("\t.lcomm %s,%d\n", exname(q->soname), off); else - printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off); + printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off); } /* @@ -932,11 +1233,15 @@ deflab1(int label) printf(LABFMT ":\n", label); } -#ifdef ELFABI +#if defined(ELFABI) + static char *loctbl[] = { "text", "data", "section .rodata,", "section .rodata" }; -#else + +#elif defined(MACHOABI) + static char *loctbl[] = { "text", "data", "section .rodata,", "cstring" }; + #endif void @@ -952,36 +1257,6 @@ setloc1(int locc) lastloc = locc; printf(" .%s\n", loctbl[locc]); } - -#if 0 -int -ftoint(NODE *p, CONSZ **c) -{ - static CONSZ cc[3]; - union { float f; double d; long double l; int i[3]; } u; - int n; - - switch (p->n_type) { - case LDOUBLE: - u.i[2] = 0; - u.l = (long double)p->n_dcon; - n = SZLDOUBLE; - break; - case DOUBLE: - u.d = (double)p->n_dcon; - n = SZDOUBLE; - break; - case FLOAT: - u.f = (float)p->n_dcon; - n = SZFLOAT; - break; - } - cc[0] = u.i[0]; - cc[1] = u.i[1]; - cc[2] = u.i[2]; - *c = cc; - return n; -} #endif /* simulate and optimise the MOD opcode */ @@ -1004,5 +1279,178 @@ simmod(NODE *p) #undef ISPOW2 /* other optimizations can go here */ - +} + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char **ary) +{ + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + +/* + * There is very little different here to the standard builtins. + * It basically handles promotion of types smaller than INT. + */ + +NODE * +powerpc_builtin_stdarg_start(NODE *f, NODE *a) +{ + NODE *p, *q; + int sz = 1; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type)) + goto bad; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + /* round up to word */ + sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue); + } + + p = buildtree(ADDROF, p, NIL); /* address of last arg */ + p = optim(buildtree(PLUS, p, bcon(sz))); + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); + tfree(f); + nfree(a); + + return p; + +bad: + uerror("bad argument to __builtin_stdarg_start"); + return bcon(0); +} + +NODE * +powerpc_builtin_va_arg(NODE *f, NODE *a) +{ + 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_sue) / SZCHAR; + if (sz < SZINT/SZCHAR) { + werror("%s%s promoted to int when passed through ...", + ISUNSIGNED(r->n_type) ? "unsigned " : "", + DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); + sz = SZINT/SZCHAR; + r->n_type = INT; + r->n_sue = MKSUE(INT); + } + + p = tcopy(a->n_left); + +#if defined(ELFABI) + + /* alignment */ + if (SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { + p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1)); + p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_sue); + } + +#endif + + /* create a copy to a temp node */ + q = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(q); + p = buildtree(ASSIGN, q, p); + + q = tempnode(tmpnr, p->n_type, p->n_df, p->n_sue); + 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_sue); + p = buildtree(UMUL, p, NIL); + p = buildtree(COMOP, q, p); + + return p; + +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); +} + +NODE * +powerpc_builtin_va_end(NODE *f, NODE *a) +{ + tfree(f); + tfree(a); + + return bcon(0); +} + +NODE * +powerpc_builtin_va_copy(NODE *f, NODE *a) +{ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM) + goto bad; + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; + +bad: + uerror("bad argument to __buildtin_va_copy"); + return bcon(0); +} + +NODE * +powerpc_builtin_return_address(NODE *f, NODE *a) +{ + int nframes; + int i = 0; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKSUE(PTR+VOID)); + regno(f) = SPREG; + + do { + f = buildtree(UMUL, f, NIL); + } while (i++ < nframes); + + f = block(PLUS, f, bcon(8), INCREF(PTR+VOID), 0, MKSUE(VOID)); + f = buildtree(UMUL, f, NIL); + + return f; +bad: + uerror("bad argument to __builtin_return_address"); + return bcon(0); } diff --git a/usr.bin/pcc/powerpc/local2.c b/usr.bin/pcc/powerpc/local2.c index 982db78eaf6..a2428ea536e 100644 --- a/usr.bin/pcc/powerpc/local2.c +++ b/usr.bin/pcc/powerpc/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.6 2007/12/22 22:56:31 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.7 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -34,29 +34,54 @@ #include <string.h> #include <stdlib.h> -int argsize(NODE *p); +#define LOWREG 0 +#define HIREG 1 -static int stkpos; - -extern struct stub stublist; -extern struct stub nlplist; +char *rnames[] = { + REGPREFIX "r0", REGPREFIX "r1", + REGPREFIX "r2", REGPREFIX "r3", + REGPREFIX "r4", REGPREFIX "r5", + REGPREFIX "r6", REGPREFIX "r7", + REGPREFIX "r8", REGPREFIX "r9", + REGPREFIX "r10", REGPREFIX "r11", + REGPREFIX "r12", REGPREFIX "r13", + REGPREFIX "r14", REGPREFIX "r15", + REGPREFIX "r16", REGPREFIX "r17", + REGPREFIX "r18", REGPREFIX "r19", + REGPREFIX "r20", REGPREFIX "r21", + REGPREFIX "r22", REGPREFIX "r23", + REGPREFIX "r24", REGPREFIX "r25", + REGPREFIX "r26", REGPREFIX "r27", + REGPREFIX "r28", REGPREFIX "r29", + REGPREFIX "r30", REGPREFIX "r31", + "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0", + "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16", + "r19r18", "r21r20", "r23r22", "r25r24", "r27r26", + "r29r28", "r31r30", + REGPREFIX "f0", REGPREFIX "f1", + REGPREFIX "f2", REGPREFIX "f3", + REGPREFIX "f4", REGPREFIX "f5", + REGPREFIX "f6", REGPREFIX "f7", + REGPREFIX "f8", REGPREFIX "f9", + REGPREFIX "f10", REGPREFIX "f11", + REGPREFIX "f12", REGPREFIX "f13", + REGPREFIX "f14", REGPREFIX "f15", + REGPREFIX "f16", REGPREFIX "f17", + REGPREFIX "f18", REGPREFIX "f19", + REGPREFIX "f20", REGPREFIX "f21", + REGPREFIX "f22", REGPREFIX "f23", + REGPREFIX "f24", REGPREFIX "f25", + REGPREFIX "f26", REGPREFIX "f27", + REGPREFIX "f28", REGPREFIX "f29", + REGPREFIX "f30", REGPREFIX "f31", +}; -static void -addstub(struct stub *list, char *name) -{ - struct stub *s; +static int argsize(NODE *p); - DLIST_FOREACH(s, list, link) { - if (strcmp(s->name, name) == 0) - return; - } - - if ((s = malloc(sizeof(struct stub))) == NULL) - cerror("addstub: malloc"); - if ((s->name = strdup(name)) == NULL) - cerror("addstub: strdup"); - DLIST_INSERT_BEFORE(list, s, link); -} +static int p2calls; +static int p2temps; /* TEMPs which aren't autos yet */ +static int p2framesize; +static int p2maxstacksize; void deflab(int label) @@ -64,89 +89,11 @@ deflab(int label) printf(LABFMT ":\n", label); } -static int regoff[7]; static TWORD ftype; -static char *funcname = NULL; /* * Print out the prolog assembler. - * addto and regoff are already calculated. */ -static void -prtprolog(struct interpass_prolog *ipp, int addto) -{ -#if 1 - int i, j; -#endif - addto = FIXEDSTACKSIZE; - - // get return address (not required for leaf function) - printf(" mflr %s\n", rnames[R0]); - // save registers R30 and R31 - printf(" stmw %s,-8(%s)\n", rnames[R30], rnames[R1]); - // save return address (not required for leaf function) - printf(" stw %s,8(%s)\n", rnames[R0], rnames[R1]); - // create the new stack frame - printf(" stwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]); - - if (kflag) { - funcname = ipp->ipp_name; - printf(" bcl 20,31,L%s$pb\n", exname(ipp->ipp_name)); - printf("L%s$pb:\n", exname(ipp->ipp_name)); - printf(" mflr %s\n", rnames[R31]); - } - -#ifdef PCC_DEBUG - if (x2debug) { - printf("ipp_regs = 0x%x\n", ipp->ipp_regs); - } -#endif - - for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++) { - if (i & 1) { - printf(" stw %s,%d(%s)\n", - rnames[j], regoff[j], rnames[FPREG]); - } - } -} - -/* - * calculate stack size and offsets - */ -static int -offcalc(struct interpass_prolog *ipp) -{ - int i, j, addto; - -#ifdef PCC_DEBUG - if (x2debug) - printf("offcalc: p2maxautooff=%d\n", p2maxautooff); -#endif - - addto = p2maxautooff; - - // space is always allocated on the stack to save the registers - for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) { - if (i & 1) { - addto += SZINT/SZCHAR; - regoff[j] = addto; - } - } - - addto += 8; /* for R31 and R30 */ - - /* round to 16-byte boundary */ - addto += 15; - addto &= ~15; - -#ifdef PCC_DEBUG - if (x2debug) - printf("offcalc: addto=%d\n", addto); -#endif - - return addto; -} - void prologue(struct interpass_prolog *ipp) { @@ -167,22 +114,47 @@ prologue(struct interpass_prolog *ipp) #endif ftype = ipp->ipp_type; - if (ipp->ipp_vis) - printf(" .globl %s\n", exname(ipp->ipp_name)); - printf(" .align 2\n"); - printf("%s:\n", exname(ipp->ipp_name)); - /* - * We here know what register to save and how much to - * add to the stack. - */ - addto = offcalc(ipp); - prtprolog(ipp, addto); + + addto = p2framesize; + + if (p2calls != 0 || kflag) { + // get return address (not required for leaf function) + printf("\tmflr %s\n", rnames[R0]); + printf("\tstw %s,8(%s)\n", rnames[R0], rnames[R1]); + } + // save registers R30 and R31 + printf("\tstmw %s,-8(%s)\n", rnames[R30], rnames[R1]); +#ifdef FPREG + printf("\tmr %s,%s\n", rnames[FPREG], rnames[R1]); +#endif + // create the new stack frame + if (addto > 65535) { + printf("\tlis %s,%d\n", rnames[R0], (-addto) >> 16); + printf("\tori %s,%s,%d\n", rnames[R0], + rnames[R0], (-addto) & 0xffff); + printf("\tstwux %s,%s,%s\n", rnames[R1], + rnames[R1], rnames[R0]); + } else { + printf("\tstwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]); + } + + if (kflag) { +#if defined(ELFABI) + printf("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n"); + printf("\tmflr %s\n", rnames[GOTREG]); +#elif defined(MACHOABI) + printf("\tbcl 20,31,L%s$pb\n", ipp->ipp_name); + printf("L%s$pb:\n", ipp->ipp_name); + printf("\tmflr %s\n", rnames[GOTREG]); +#endif + } + } + void eoftn(struct interpass_prolog *ipp) { - int i, j; #ifdef PCC_DEBUG if (x2debug) @@ -192,30 +164,18 @@ eoftn(struct interpass_prolog *ipp) if (ipp->ipp_ip.ip_lbl == 0) return; /* no code needs to be generated */ - /* return from function code */ - for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) { - if (i & 1) - printf("\tlwz %s,%d(%s)\n", - rnames[j], regoff[j], rnames[FPREG]); - - } - -// assert(ftype != ipp->ipp_type); - /* struct return needs special treatment */ - if (ftype == STRTY || ftype == UNIONTY) { - assert(0); - printf(" movl 8(%%ebp),%%eax\n"); - printf(" leave\n"); - printf(" ret $4\n"); - } else { - // unwind stack frame - printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]); + if (ftype == STRTY || ftype == UNIONTY) + cerror("eoftn"); + + /* unwind stack frame */ + printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]); + if (p2calls != 0 || kflag) { printf("\tlwz %s,8(%s)\n", rnames[R0], rnames[R1]); printf("\tmtlr %s\n", rnames[R0]); - printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]); - printf("\tblr\n"); } + printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]); + printf("\tblr\n"); } /* @@ -324,305 +284,556 @@ twollcomp(NODE *p) } if (p->n_op >= ULE) cb1 += 4, cb2 += 4; - expand(p, 0, "\tcmplw UR,UL # compare 64-bit values (upper)\n"); + if (p->n_op >= ULE) + expand(p, 0, "\tcmplw UL,UR" COM "compare 64-bit values (upper)\n"); + else + expand(p, 0, "\tcmpw UL,UR" COM "compare 64-bit values (upper)\n"); if (cb1) cbgen(cb1, s); if (cb2) cbgen(cb2, e); - expand(p, 0, "\tcmplw AR,AL # (and lower)\n"); + if (p->n_op >= ULE) + expand(p, 0, "\tcmplw AL,AR" COM "(and lower)\n"); + else + expand(p, 0, "\tcmpw AL,AR" COM "(and lower)\n"); cbgen(p->n_op, e); deflab(s); } -#if 0 +static void +shiftop(NODE *p) +{ + NODE *r = p->n_right; + TWORD ty = p->n_type; + + if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tsrwi A1,AL,32-AR" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tslwi U1,UL,AR\n"); + expand(p, INBREG, "\tor U1,U1,A1\n"); + expand(p, INBREG, "\tslwi A1,AL,AR\n"); + } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) { + expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n"); + if (r->n_lval == 32) + expand(p, INBREG, "\tmr U1,AL\n"); + else + expand(p, INBREG, "\tslwi U1,AL,AR-32\n"); + } else if (p->n_op == LS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tslwi U1,UL,32-AR" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tsrwi A1,AL,AR\n"); + expand(p, INBREG, "\tor A1,A1,U1\n"); + if (ty == LONGLONG) + expand(p, INBREG, "\tsrawi U1,UL,AR\n"); + else + expand(p, INBREG, "\tsrwi U1,UL,AR\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) { + if (ty == LONGLONG) + expand(p, INBREG, "\tli U1,-1" COM "64-bit right-shift\n"); + else + expand(p, INBREG, "\tli U1,0" COM "64-bit right-shift\n"); + if (r->n_lval == 32) + expand(p, INBREG, "\tmr A1,UL\n"); + else if (ty == LONGLONG) + expand(p, INBREG, "\tsrawi A1,UL,AR-32\n"); + else + expand(p, INBREG, "\tsrwi A1,UL,AR-32\n"); + } else if (p->n_op == RS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } +} + /* - * Assign to a bitfield. - * Clumsy at least, but what to do? + * Structure assignment. */ static void -bfasg(NODE *p) +stasg(NODE *p) { - NODE *fn = p->n_left; - int shift = UPKFOFF(fn->n_rval); - int fsz = UPKFSZ(fn->n_rval); - int andval, tch = 0; - - /* get instruction size */ - switch (p->n_type) { - case CHAR: case UCHAR: tch = 'b'; break; - case SHORT: case USHORT: tch = 'w'; break; - case INT: case UNSIGNED: tch = 'l'; break; - default: comperr("bfasg"); + /* R3 = dest, R4 = src, R5 = len */ + printf("\tli %s,%d\n", rnames[R5], p->n_stsize); + if (p->n_left->n_op == OREG) { + printf("\taddi %s,%s," CONFMT "\n", + rnames[R3], rnames[regno(p->n_left)], + p->n_left->n_lval); + } else if (p->n_left->n_op == NAME) { +#if defined(ELFABI) + printf("\tli %s,", rnames[R3]); + adrput(stdout, p->n_left); + printf("@ha\n"); + printf("\taddi %s,%s,", rnames[R3], rnames[R3]); + adrput(stdout, p->n_left); + printf("@l\n"); +#elif defined(MACHOABI) + printf("\tli %s,ha16(", rnames[R3]); + adrput(stdout, p->n_left); + printf(")\n"); + printf("\taddi %s,%s,lo16(", rnames[R3], rnames[R3]); + adrput(stdout, p->n_left); + printf(")\n"); +#endif + } + if (kflag) { +#if defined(ELFABI) + printf("\tbl %s@got(30)\n", exname("memcpy")); +#elif defined(MACHOABI) + printf("\tbl L%s$stub\n", "memcpy"); + addstub(&stublist, "memcpy"); +#endif + } else { + printf("\tbl %s\n", exname("memcpy")); } +} - /* put src into a temporary reg */ - fprintf(stdout, " mov%c ", tch); - adrput(stdout, getlr(p, 'R')); - fprintf(stdout, ","); - adrput(stdout, getlr(p, '1')); - fprintf(stdout, "\n"); - - /* AND away the bits from dest */ - andval = ~(((1 << fsz) - 1) << shift); - fprintf(stdout, " and%c $%d,", tch, andval); - adrput(stdout, fn->n_left); - fprintf(stdout, "\n"); - - /* AND away unwanted bits from src */ - andval = ((1 << fsz) - 1); - fprintf(stdout, " and%c $%d,", tch, andval); - adrput(stdout, getlr(p, '1')); - fprintf(stdout, "\n"); - - /* SHIFT left src number of bits */ - if (shift) { - fprintf(stdout, " sal%c $%d,", tch, shift); - adrput(stdout, getlr(p, '1')); - fprintf(stdout, "\n"); +static void +fpemul(NODE *p) +{ + NODE *l = p->n_left; + char *ch = NULL; + + if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; + else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; + else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3"; + + else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; + else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; + else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3"; + + else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; + else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; + else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3"; + + else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; + else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; + else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3"; + + else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; + else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; + else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2"; + + else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; + else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; + else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2"; + + else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; + else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; + else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2"; + + else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; + else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; + else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2"; + + else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; + else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; + else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2"; + + else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; + else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; + else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2"; + + else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; + else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; + else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2"; + + else if (p->n_op == SCONV && p->n_type == FLOAT) { + if (l->n_type == DOUBLE) ch = "truncdfsf2"; + else if (l->n_type == LDOUBLE) ch = "truncdfsf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdisf"; + else if (l->n_type == LONGLONG) ch = "floatdisf"; + else if (l->n_type == LONG) ch = "floatsisf"; + else if (l->n_type == ULONG) ch = "floatunsisf"; + else if (l->n_type == INT) ch = "floatsisf"; + else if (l->n_type == UNSIGNED) ch = "floatunsisf"; + } else if (p->n_op == SCONV && p->n_type == DOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == LDOUBLE) ch = "truncdfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunssidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunssidf"; + } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == DOUBLE) ch = "extenddfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunssidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONGLONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixtfdi"; + } else if (p->n_op == SCONV && p->n_type == LONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixtfdi"; + } else if (p->n_op == SCONV && p->n_type == ULONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunstfdi"; + } else if (p->n_op == SCONV && p->n_type == INT) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { + if (l->n_type == FLOAT) ch = "fixunssfsi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; } - /* OR in src to dest */ - fprintf(stdout, " or%c ", tch); - adrput(stdout, getlr(p, '1')); - fprintf(stdout, ","); - adrput(stdout, fn->n_left); - fprintf(stdout, "\n"); -} + if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); + + if (kflag) { +#if defined(ELFABI) + printf("\tbl __%s@got(30)" COM "soft-float\n", exname(ch)); +#elif defined(MACHOABI) + char buf[32]; + printf("\tbl L__%s$stub" COM "soft-float\n", ch); + snprintf(buf, 32, "__%s", ch); + addstub(&stublist, buf); #endif + } else { + printf("\tbl __%s" COM "soft-float\n", exname(ch)); + } + + if (p->n_op >= EQ && p->n_op <= GT) + printf("\tcmpwi %s,0\n", rnames[R3]); +} -#if 0 /* - * Push a structure on stack as argument. - * the scratch registers are already free here + * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines */ + static void -starg(NODE *p) +emul(NODE *p) { - FILE *fp = stdout; - - fprintf(fp, " subl $%d,%%esp\n", p->n_stsize); - fprintf(fp, " pushl $%d\n", p->n_stsize); - expand(p, 0, " pushl AL\n"); - expand(p, 0, " leal 8(%esp),A1\n"); - expand(p, 0, " pushl A1\n"); - fprintf(fp, " call memcpy\n"); - fprintf(fp, " addl $12,%%esp\n"); -} + char *ch = NULL; + + if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3"; + else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG || + DEUNSIGN(p->n_type) == INT)) + ch = "ashlsi3"; + + else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3"; + else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT)) + ch = "lshrsi3"; + + else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3"; + else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT)) + ch = "ashrsi3"; + + else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; + else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT)) + ch = "divsi3"; + + else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; + else if (p->n_op == DIV && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "udivsi3"; + + else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; + else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT)) + ch = "modsi3"; + + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; + else if (p->n_op == MOD && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "umodsi3"; + + else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; + else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT)) + ch = "mulsi3"; + + else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2"; + else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2"; + + else ch = 0, comperr("ZE"); + if (kflag) { +#if defined(ELFABI) + printf("\tbl __%s@got(30)" COM "emulated op\n", exname(ch)); +#elif defined(MACHOABI) + char buf[32]; + printf("\tbl L__%s$stub" COM "emulated op\n", ch); + snprintf(buf, 32, "__%s", ch); + addstub(&stublist, buf); #endif + } else { + printf("\tbl __%s" COM "emulated operation\n", exname(ch)); + } +} -#if 0 /* - * Compare two floating point numbers. + * Floating-point conversions (int -> float/double & float/double -> int) */ + static void -fcomp(NODE *p) +ftoi(NODE *p) { - if (p->n_left->n_op == REG) { - if (p->n_su & DORIGHT) - expand(p, 0, " fxch\n"); - expand(p, 0, " fucompp\n"); /* emit compare insn */ - } else if (p->n_left->n_type == DOUBLE) - expand(p, 0, " fcompl AL\n"); /* emit compare insn */ - else if (p->n_left->n_type == FLOAT) - expand(p, 0, " fcomp AL\n"); /* emit compare insn */ - else - comperr("bad compare %p\n", p); - expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */ - - switch (p->n_op) { - case EQ: - expand(p, 0, " andb $64,%ah\n jne LC\n"); - break; - case NE: - expand(p, 0, " andb $64,%ah\n je LC\n"); - break; - case LE: - expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n"); - break; - case LT: - expand(p, 0, " andb $65,%ah\n je LC\n"); - break; - case GT: - expand(p, 0, " andb $1,%ah\n jne LC\n"); - break; - case GE: - expand(p, 0, " andb $65,%ah\n jne LC\n"); - break; - default: - comperr("fcomp op %d\n", p->n_op); + NODE *l = p->n_left; + + printf(COM "start conversion float/(l)double to int\n"); + + if (l->n_op != OREG) { + expand(p, 0, "\tstw AL,-4"); + printf("(%s)\n", rnames[SPREG]); + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A2,"); + else + expand(p, 0, "\tlfd A2,\n"); + printf("-4(%s)\n", rnames[SPREG]); + } else { + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A2,AL\n"); + else + expand(p, 0, "\tlfd A2,AL\n"); } + + expand(p, 0, "\tfctiwz A2,A2\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + + printf(COM "end conversion\n"); } -#endif -#if 0 -/* - * Convert an unsigned long long to floating point number. - */ static void -ulltofp(NODE *p) +ftou(NODE *p) { - static int loadlab; - int jmplab; - - if (loadlab == 0) { - loadlab = getlab(); - expand(p, 0, " .data\n"); - printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab); - expand(p, 0, " .text\n"); + static int lab = 0; + NODE *l = p->n_left; + int lab1 = getlab(); + int lab2 = getlab(); + + printf(COM "start conversion of float/(l)double to unsigned\n"); + + if (lab == 0) { + lab = getlab(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x41e00000\n\t.long 0\n", lab); + expand(p, 0, "\t.text\n"); + } + + if (l->n_op != OREG) { + expand(p, 0, "\tstw AL,"); + printf("-4(%s)\n", rnames[SPREG]); + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A3,"); + else + expand(p, 0, "\tlfd A3,"); + printf("-4(%s)\n", rnames[SPREG]); + + } else { + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A3,AL\n"); + else + expand(p, 0, "\tlfd A3,AL\n"); + } + +#if 0 + if (kflag) { + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + printf("-L%s$pb)", cftnsp->soname); + expand(p, 0, "(A1)\n"); + } else { + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "\n", lab); } - jmplab = getlab(); - 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 "\n", loadlab); - printf(" faddp %%st,%%st(1)\n"); - printf(LABFMT ":\n", jmplab); -} #endif -static int -argsiz(NODE *p) -{ - TWORD t = p->n_type; +#if defined(ELFABI) - if (t < LONGLONG || t == FLOAT || t > BTMASK) - return 4; - if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) - return 8; - if (t == LDOUBLE) - return 12; - if (t == STRTY || t == UNIONTY) - return p->n_stsize; - comperr("argsiz"); - return 0; + expand(p, 0, "\taddis A1,"); + printf("%s," LABFMT "@ha\n", rnames[R31], lab); + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "@l", lab); + expand(p, 0, "(A1)\n"); + +#elif defined(MACHOABI) + + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname); + printf(")\n"); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname); + expand(p, 0, ")(A1)\n"); + +#endif + + expand(p, 0, "\tfcmpu cr7,A3,A2\n"); + printf("\tcror 30,29,30\n"); + printf("\tbeq cr7,"LABFMT "\n", lab1); + + expand(p, 0, "\tfctiwz A2,A3\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + printf("\tba " LABFMT "\n", lab2); + + deflab(lab1); + + expand(p, 0, "\tfsub A2,A3,A2\n"); + expand(p, 0, "\tfctiwz A2,A2\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + expand(p, 0, "\txoris A1,A1,0x8000\n"); + + deflab(lab2); + + printf(COM "end conversion\n"); } -void -zzzcode(NODE *p, int c) +static void +itof(NODE *p) { -#if 0 - NODE *r, *l; - int pr, lr, s; - char *ch; -#endif - char inst[50]; + static int labu = 0; + static int labi = 0; + int lab; + NODE *l = p->n_left; + + printf(COM "start conversion (u)int to float/(l)double\n"); + + if (labi == 0 && l->n_type == INT) { + labi = getlab(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x43300000\n\t.long 0x80000000\n", labi); + expand(p, 0, "\t.text\n"); + } else if (labu == 0 && l->n_type == UNSIGNED) { + labu = getlab(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x43300000\n\t.long 0x00000000\n", labu); + expand(p, 0, "\t.text\n"); + } + + if (l->n_type == INT) { + expand(p, 0, "\txoris A1,AL,0x8000\n"); + lab = labi; + } else { + lab = labu; + } + expand(p, 0, "\tstw A1,"); + printf("-4(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlis A1,0x4330\n"); + expand(p, 0, "\tstw A1,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlfd A3,"); + printf("-8(%s)\n", rnames[SPREG]); - switch (c) { #if 0 - case 'C': /* remove from stack after subroutine call */ - pr = p->n_qual; - if (p->n_op == STCALL || p->n_op == USTCALL) - pr += 4; - if (p->n_op == UCALL) - return; /* XXX remove ZC from UCALL */ - if (pr) - printf(" addl $%d, %s\n", pr, rnames[ESP]); - break; + if (kflag) { + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + printf("-L%s$pb)", cftnsp->soname); + expand(p, 0, "(A1)\n"); + } else { + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "\n", lab); + } #endif - case 'D': /* Long long comparision */ - twollcomp(p); - break; +#if defined(ELFABI) -#if 0 - case 'E': /* Assign to bitfield */ - bfasg(p); - break; + expand(p, 0, "\taddis A1,"); + printf("%s," LABFMT "@ha\n", rnames[R31], lab); + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "@l", lab); + expand(p, 0, "(A1)\n"); - case 'F': /* Structure argument */ - if (p->n_stalign != 0) /* already on stack */ - starg(p); - break; +#elif defined(MACHOABI) - case 'G': /* Floating point compare */ - fcomp(p); - break; + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname); + printf(")\n"); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname); + expand(p, 0, ")(A1)\n"); - case 'J': /* convert unsigned long long to floating point */ - ulltofp(p); - break; +#endif - case 'N': /* output extended reg name */ - printf("%s", rnames[getlr(p, '1')->n_rval]); - break; + expand(p, 0, "\tfsub A3,A3,A2\n"); + if (p->n_type == FLOAT) + expand(p, 0, "\tfrsp A3,A3\n"); + + printf(COM "end conversion\n"); +} + + +static void +fpconv(NODE *p) +{ + NODE *l = p->n_left; + +#ifdef PCC_DEBUG + if (p->n_op != SCONV) + cerror("fpconv 1"); #endif - case 'O': /* 64-bit left and right shift operators */ + if (DEUNSIGN(l->n_type) == INT) + itof(p); + else if (p->n_type == INT) + ftoi(p); + else if (p->n_type == UNSIGNED) + ftou(p); + else + cerror("unhandled floating-point conversion"); - if (p->n_op == LS && p->n_right->n_lval < 32) { - expand(p, INBREG, "\tsrwi A1,AL,32-AR ; 64-bit left-shift\n"); - expand(p, INBREG, "\tslwi U1,UL,AR\n"); - expand(p, INBREG, "\tor U1,U1,A1\n"); - expand(p, INBREG, "\tslwi A1,AL,AR\n"); - } else if (p->n_op == LS) { - expand(p, INBREG, "\tli A1,0 ; 64-bit left-shift\n"); - expand(p, INBREG, "\tslwi U1,AL,AR-32\n"); - } else if (p->n_op == RS && p->n_right->n_lval < 32) { - expand(p, INBREG, "\tslwi U1,UL,32-AR ; 64-bit right-shift\n"); - expand(p, INBREG, "\tsrwi A1,AL,AR\n"); - expand(p, INBREG, "\tor A1,A1,U1\n"); - expand(p, INBREG, "\tsrwi U1,UL,AR\n"); - } else if (p->n_op == RS) { - expand(p, INBREG, "\tli U1,0 ; 64-bit right-shift\n"); - expand(p, INBREG, "\tsrwi A1,UL,AR-32\n"); - } +} + +void +zzzcode(NODE *p, int c) +{ + switch (c) { + + case 'C': /* floating-point conversions */ + fpconv(p); break; + case 'D': /* long long comparision */ + twollcomp(p); + break; -#if 0 - case 'O': /* print out emulated ops */ - pr = 16; - if (p->n_op == RS || p->n_op == LS) { - expand(p, INAREG, "\tpushl AR\n"); - pr = 12; - } else - 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 == MUL) ch = "mul"; - 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 == RS && p->n_type == ULONGLONG) ch = "lshr"; - else if (p->n_op == RS) ch = "ashr"; - else if (p->n_op == LS) ch = "ashl"; - else ch = 0, comperr("ZO"); - printf("\tbl __%sdi3\n\n", ch,); - break; -#endif + case 'E': /* print out emulated ops */ + emul(p); + break; -#if 0 - case 'P': /* push hidden argument on stack */ - r = (NODE *)p->n_sue; - printf("\tleal -%d(%%ebp),", stkpos); - adrput(stdout, getlr(p, '1')); - printf("\n\tpushl "); - adrput(stdout, getlr(p, '1')); - putchar('\n'); + case 'F': /* print out emulate floating-point ops */ + fpemul(p); break; -#endif - case 'Q': /* emit struct assign */ - if (p->n_stsize == 4) { - int sz = sizeof inst; - - snprintf(inst, sz, "\tlwz %s,0(AR)\n", rnames[R5]); - expand(p, INAREG, inst); - snprintf(inst, sz, "\tstw %s,AL\n", rnames[R5]); - expand(p, INAREG, inst); - return; - } + case 'O': /* 64-bit left and right shift operators */ + shiftop(p); + break; - if ((p->n_stsize & ~0xffff) != 0) { - printf("\tlis %s,%d\n", rnames[R5], p->n_stsize & 0xffff); - printf("\taddis %s,%s,%d\n", rnames[R5], rnames[R5], (p->n_stsize >> 16) & 0xffff); - } else { - printf("\tli %s,%d\n", rnames[R5], p->n_stsize); - } - printf("\taddi %s,%s,%lld\n", rnames[R3], rnames[p->n_left->n_rval], p->n_left->n_lval); - printf("\tbl %s%s\n", exname("memcpy"), - kflag ? "$stub" : ""); - addstub(&stublist, exname("memcpy")); + case 'Q': /* emit struct assign */ + stasg(p); break; default: @@ -643,16 +854,41 @@ canaddr(NODE *p) { int o = p->n_op; - if (o==NAME || o==REG || o==ICON || o==OREG || - (o==UMUL && shumul(p->n_left))) + if (o == NAME || o == REG || o == ICON || o == OREG || + (o == UMUL && shumul(p->n_left))) return(1); - return(0); + return 0; } int fldexpand(NODE *p, int cookie, char **cp) { - return 0; + CONSZ val; + int shft; + + if (p->n_op == ASSIGN) + p = p->n_left; + + shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval); + + switch (**cp) { + case 'S': + printf("%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("%d", shft); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= shft; + printf(CONFMT, (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; } /* @@ -685,10 +921,10 @@ shtemp(NODE *p) switch (p->n_op) { case REG: - return (!istreg(p->n_rval)); + return (!istreg(regno(p))); case OREG: - r = p->n_rval; + r = regno(p); if (R2TEST(r)) { if (istreg(R2UPK1(r))) return(0); @@ -716,46 +952,20 @@ adrcon(CONSZ val) void conput(FILE *fp, NODE *p) { - char *s; int val = p->n_lval; switch (p->n_op) { case ICON: -#if 0 - if (p->n_sp) - printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel); -#endif - if (p->n_sp == NULL || (p->n_sp->sclass == ILABEL || - (p->n_sp->sclass == STATIC && p->n_sp->slevel > 0))) - s = p->n_name; - else - s = exname(p->n_name); - - if (*s != '\0') { - if (kflag && p->n_sp && ISFTN(p->n_sp->stype)) { - if (p->n_sp && p->n_sp->sclass == EXTERN) { - fprintf(fp, "%s$stub", s); - addstub(&stublist, s); - } else { - fprintf(fp, "%s", s); - } - } else if (kflag) { - if (p->n_sp && p->n_sp->sclass == EXTERN) { - fprintf(fp, "L%s$non_lazy_ptr", s); - addstub(&nlplist, s); - } else { - fprintf(fp, "%s", s); - } - fprintf(fp, "-L%s$pb", exname(funcname)); - } else { - fprintf(fp, "%s", s); - } - if (val > 0) + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) fprintf(fp, "+%d", val); - else if (val < 0) - fprintf(fp, "-%d", -val); - } else - fprintf(fp, "%d", val); + } else { + if (GCLASS(p->n_type) == CLASSB) + fprintf(fp, CONFMT, p->n_lval >> 32); + else + fprintf(fp, "%d", val); + } return; default: @@ -774,19 +984,20 @@ insput(NODE *p) * Print lower or upper name of 64-bit register. */ static void -reg64name(int rval, int hi) +reg64name(int reg, int hi) { - int off = 3 * (hi != 0); + int idx; + int off = 0; -#ifdef ELFABI - fputc('%', stdout); -#endif + assert(GCLASS(reg) == CLASSB); + + idx = (reg > R14R15 ? (2*(reg - R14R15) + R14) : (reg - R3R4 + R3)); - fprintf(stdout, "%c%c", - rnames[rval][off], - rnames[rval][off + 1]); - if (rnames[rval][off + 2]) - fputc(rnames[rval][off + 2], stdout); + if ((hi == HIREG && !features(FEATURE_BIGENDIAN)) || + (hi == LOWREG && features(FEATURE_BIGENDIAN))) + off = 1; + + fprintf(stdout, "%s" , rnames[idx + off]); } /* @@ -796,22 +1007,25 @@ reg64name(int rval, int hi) void upput(NODE *p, int size) { - size /= SZCHAR; switch (p->n_op) { case REG: - reg64name(p->n_rval, 1); + reg64name(regno(p), HIREG); break; case NAME: case OREG: - p->n_lval += size; - adrput(stdout, p); - p->n_lval -= size; + if (features(FEATURE_BIGENDIAN)) + fprintf(stdout, "%d", (int)p->n_lval); + else + fprintf(stdout, "%d", (int)(p->n_lval + 4)); + fprintf(stdout, "(%s)", rnames[regno(p)]); break; + case ICON: fprintf(stdout, CONFMT, p->n_lval >> 32); break; + default: comperr("upput bad op %d size %d", p->n_op, size); } @@ -820,7 +1034,6 @@ upput(NODE *p, int size) void adrput(FILE *io, NODE *p) { - int r; /* output an address, with offsets, from p */ if (p->n_op == FLD) @@ -830,19 +1043,7 @@ adrput(FILE *io, NODE *p) case NAME: if (p->n_name[0] != '\0') { - if (kflag && p->n_sp && (p->n_sp->sclass == EXTERN || p->n_sp->sclass == EXTDEF)) { - fprintf(io, "L%s$non_lazy_ptr", exname(p->n_name)); - addstub(&nlplist, exname(p->n_name)); - fprintf(io, "-L%s$pb", exname(funcname)); - } else if (kflag && p->n_sp && p->n_sp->sclass == STATIC && p->n_sp->slevel == 0) { - fprintf(io, "%s", exname(p->n_name)); - fprintf(io, "-L%s$pb", exname(funcname)); - } else if (kflag && p->n_sp && (p->n_sp->sclass == ILABEL || (p->n_sp->sclass == STATIC && p->n_sp->sclass > 0))) { - fprintf(io, "%s", p->n_name); - fprintf(io, "-L%s$pb", exname(funcname)); - } else { - fputs(p->n_name, io); - } + fputs(p->n_name, io); if (p->n_lval != 0) fprintf(io, "+" CONFMT, p->n_lval); } else @@ -850,9 +1051,12 @@ adrput(FILE *io, NODE *p) return; case OREG: - r = p->n_rval; - fprintf(io, "%d", (int)p->n_lval); - fprintf(io, "(%s)", rnames[p->n_rval]); + if (DEUNSIGN(p->n_type) == LONGLONG && + features(FEATURE_BIGENDIAN)) + fprintf(io, "%d", (int)(p->n_lval + 4)); + else + fprintf(io, "%d", (int)p->n_lval); + fprintf(io, "(%s)", rnames[regno(p)]); return; case ICON: @@ -860,16 +1064,28 @@ adrput(FILE *io, NODE *p) conput(io, p); return; - case MOVE: case REG: + if (GCLASS(regno(p)) == CLASSB) + reg64name(regno(p), LOWREG); + else + fprintf(io, "%s", rnames[regno(p)]); +#if 0 switch (p->n_type) { + case DOUBLE: + case LDOUBLE: + if (features(FEATURE_HARDFLOAT)) { + fprintf(io, "%s", rnames[regno(p)]); + break; + } + /* FALL-THROUGH */ case LONGLONG: case ULONGLONG: - reg64name(p->n_rval, 0); + reg64name(regno(p), LOWREG); break; default: - fprintf(io, "%s", rnames[p->n_rval]); + fprintf(io, "%s", rnames[regno(p)]); } +#endif return; default: @@ -910,15 +1126,58 @@ cbgen(int o, int lab) printf("\t%s " LABFMT "\n", ccbranches[o-EQ], lab); } +static int +argsize(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + if (t == LONGLONG || t == ULONGLONG) + return 8; + if (t == DOUBLE || t == LDOUBLE) + return 8; + if (t == STRTY || t == UNIONTY) + return p->n_stsize; + comperr("argsize"); + return 0; +} + +static int +calc_args_size(NODE *p) +{ + int n = 0; + + if (p->n_op == CM) { + n += calc_args_size(p->n_left); + n += calc_args_size(p->n_right); + return n; + } + + n += argsize(p); + + return n; +} + + static void fixcalls(NODE *p) { - /* Prepare for struct return by allocating bounce space on stack */ + int n = 0; + switch (p->n_op) { case STCALL: + case CALL: + n = calc_args_size(p->n_right); + if (n > p2maxstacksize) + p2maxstacksize = n; + /* FALLTHROUGH */ case USTCALL: - if (p->n_stsize+p2autooff > stkpos) - stkpos = p->n_stsize+p2autooff; + case UCALL: + ++p2calls; + break; + case TEMP: + p2temps += argsize(p); break; } } @@ -949,9 +1208,9 @@ storefloat(struct interpass *ip, NODE *p) int off; off = BITOOR(freetemp(szty(t))); - ll = mklnode(OREG, off, FPREG, t); + ll = mklnode(OREG, off, SPREG, t); nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t)); - p->n_left = mklnode(OREG, off, FPREG, t); + p->n_left = mklnode(OREG, off, SPREG, t); DLIST_INSERT_BEFORE(ip, nip, qelem); } return l|r; @@ -971,17 +1230,38 @@ myreader(struct interpass *ipole) { struct interpass *ip; - stkpos = p2autooff; + p2calls = 0; + p2temps = 0; + p2maxstacksize = 0; + DLIST_FOREACH(ip, ipole, qelem) { if (ip->type != IP_NODE) continue; walkf(ip->ip_node, fixcalls); storefloat(ip, ip->ip_node); } - if (stkpos > p2autooff) - p2autooff = stkpos; - if (stkpos > p2maxautooff) - p2maxautooff = stkpos; + + if (p2maxstacksize < NARGREGS*SZINT/SZCHAR) + p2maxstacksize = NARGREGS*SZINT/SZCHAR; + + p2framesize = ARGINIT/SZCHAR; /* stack ptr / return addr */ + p2framesize += 8; /* for R31 and R30 */ + p2framesize += p2maxautooff; /* autos */ + p2framesize += p2temps; /* TEMPs that aren't autos */ + if (p2calls != 0) + p2framesize += p2maxstacksize; /* arguments to functions */ + p2framesize += (ALSTACK/SZCHAR - 1); /* round to 16-byte boundary */ + p2framesize &= ~(ALSTACK/SZCHAR - 1); + +#if 0 + printf("!!! MYREADER\n"); + printf("!!! p2maxautooff = %d\n", p2maxautooff); + printf("!!! p2autooff = %d\n", p2autooff); + printf("!!! p2temps = %d\n", p2temps); + printf("!!! p2calls = %d\n", p2calls); + printf("!!! p2maxstacksize = %d\n", p2maxstacksize); +#endif + if (x2debug) printip(ipole); } @@ -1038,42 +1318,51 @@ void rmove(int s, int d, TWORD t) { switch (t) { + case LDOUBLE: + case DOUBLE: + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALL-THROUGH */ case LONGLONG: case ULONGLONG: if (s == d+1) { /* dh = sl, copy low word first */ printf("\tmr "); - reg64name(d,0); + reg64name(d, LOWREG); printf(","); - reg64name(s,0); + reg64name(s, LOWREG); printf("\n"); printf("\tmr "); - reg64name(d,1); + reg64name(d, HIREG); printf(","); - reg64name(s,1); + reg64name(s, HIREG); printf("\n"); } else { /* copy high word first */ printf("\tmr "); - reg64name(d,1); + reg64name(d, HIREG); printf(","); - reg64name(s,1); + reg64name(s, HIREG); printf("\n"); printf("\tmr "); - reg64name(d,0); + reg64name(d, LOWREG); printf(","); - reg64name(s,0); + reg64name(s, LOWREG); printf("\n"); } break; - case LDOUBLE: -#ifdef notdef - /* a=b()*c(); will generate this */ - comperr("bad float rmove: %d %d", s, d); -#endif - break; + case FLOAT: + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALL-THROUGH */ default: - printf("\tmr %s,%s\n", rnames[d], rnames[s]); + printf("\tmr %s,%s" COM "rmove\n", rnames[d], rnames[s]); } } @@ -1092,57 +1381,52 @@ COLORMAP(int c, int *r) { int num = 0; - switch (c) { - case CLASSA: - num += r[CLASSA]; - num += 2*r[CLASSB]; - return num < 30; - case CLASSB: - num += 2*r[CLASSB]; - num += r[CLASSA]; - return num < 16; - } - assert(0); - return 0; /* XXX gcc */ + switch (c) { + case CLASSA: + num += r[CLASSA]; + num += 2*r[CLASSB]; + return num < 30; + case CLASSB: + num += 2*r[CLASSB]; + num += r[CLASSA]; + return num < 16; + case CLASSC: + return num < 32; + } + assert(0); + return 0; /* XXX gcc */ } -#ifdef ELFABI -char *rnames[] = { - "%r0", "%r1", "%r2", "%r3","%r4","%r5", "%r6", "%r7", "%r8", - "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", - "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", "%r24", - "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", - /* the order is flipped, because we are big endian */ - "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0", - "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16", - "r19r18", "r21r20", "r23r22", "r25r24", "r27r26", - "r29r28", "r31r30", -}; -#else -char *rnames[] = { - "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", "r8", - "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", - "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", - "r25", "r26", "r27", "r28", "r29", "r30", "r31", - /* the order is flipped, because we are big endian */ - "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0", - "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16", - "r19r18", "r21r20", "r23r22", "r25r24", "r27r26", - "r29r28", "r31r30", -}; -#endif - /* * Return a class suitable for a specific type. */ int gclass(TWORD t) { - if (t == FLOAT || t == DOUBLE || t == LDOUBLE) + if (t == LONGLONG || t == ULONGLONG) return CLASSB; + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + if (t == FLOAT) + return CLASSA; + else + return CLASSB; + } return CLASSA; } +int +retreg(int t) +{ + int c = gclass(t); + if (c == CLASSB) + return R3R4; + else if (c == CLASSC) + return F1; + return R3; +} + /* * Calculate argument sizes. */ @@ -1160,9 +1444,10 @@ lastcall(NODE *p) p->n_qual = 0; if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) - size += argsiz(p->n_right); - size += argsiz(p); + size += argsize(p->n_right); + size += argsize(p); op->n_qual = size; /* XXX */ } @@ -1180,17 +1465,37 @@ special(NODE *p, int shape) return SRREG; break; case SPCON: - if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0xffff) == 0) + if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0x7fff) == 0) return SRDIR; break; } return SRNOPE; } +static int fset = FEATURE_BIGENDIAN | FEATURE_HARDFLOAT; + /* * Target-dependent command-line options. */ void mflags(char *str) { + if (strcasecmp(str, "big-endian") == 0) { + fset |= FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "little-endian") == 0) { + fset &= ~FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "soft-float") == 0) { + fset &= ~FEATURE_HARDFLOAT; + } else if (strcasecmp(str, "hard-float") == 0) { + fset |= FEATURE_HARDFLOAT; + } else { + fprintf(stderr, "unknown m option '%s'\n", str); + exit(1); + } +} + +int +features(int mask) +{ + return ((fset & mask) == mask); } diff --git a/usr.bin/pcc/powerpc/macdefs.h b/usr.bin/pcc/powerpc/macdefs.h index 8f9f3746f09..72abba8755f 100644 --- a/usr.bin/pcc/powerpc/macdefs.h +++ b/usr.bin/pcc/powerpc/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.3 2007/12/22 14:05:04 stefan Exp $ */ +/* $OpenBSD: macdefs.h,v 1.4 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -30,6 +30,8 @@ * Machine-dependent defines for both passes. */ +#define ELFABI + /* * Convert (multi-)character constant to integer. */ @@ -59,11 +61,15 @@ #define ALDOUBLE 32 #define ALLDOUBLE 32 #define ALLONG 32 +#ifdef ELFABI +#define ALLONGLONG 64 +#else #define ALLONGLONG 32 +#endif #define ALSHORT 16 #define ALPOINT 32 #define ALSTRUCT 32 -#define ALSTACK 32 +#define ALSTACK (16*SZCHAR) /* * Min/max values. @@ -85,12 +91,9 @@ #define MAX_ULONGLONG 0xffffffffffffffffULL #define CHAR_UNSIGNED -#define TARGET_STDARGS #define BOOL_TYPE INT /* what used to store _Bool */ #define WCHAR_TYPE INT /* what used to store wchar_t */ -#define ELFABI - /* * Use large-enough types. */ @@ -99,33 +102,32 @@ typedef unsigned long long U_CONSZ; typedef long long OFFSZ; #define CONFMT "%lld" /* format for printing constants */ -#ifdef ELFABI +#if defined(ELFABI) #define LABFMT ".L%d" /* format for printing labels */ -#else +#define REGPREFIX "%" /* format for printing registers */ +#elif defined(MACHOABI) #define LABFMT "L%d" /* format for printing labels */ +#define REGPREFIX +#else +#error undefined ABI #endif #define STABLBL "LL%d" /* format for stab (debugging) labels */ + +#ifdef MACHOABI #define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ +#endif #undef FIELDOPS /* no bit-field instructions */ -#if 0 -#define RTOLBYTES /* bytes are numbered right to left */ -#endif #define ENUMSIZE(high,low) INT /* enums are always stored in full int */ /* Definitions mostly used in pass2 */ #define BYTEOFF(x) ((x)&03) -#define wdal(k) (BYTEOFF(k)==0) #define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ -#define STOARG(p) -#define STOFARG(p) -#define STOSTARG(p) - -#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \ - (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1) +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || \ + DEUNSIGN(t) == LONGLONG) ? 2 : 1) /* * The PPC register definition are taken from apple docs. @@ -133,6 +135,7 @@ typedef long long OFFSZ; * The classes used are: * A - general registers * B - 64-bit register pairs + * C - floating-point registers */ #define R0 0 // scratch register @@ -185,25 +188,110 @@ typedef long long OFFSZ; #define R28R29 46 #define R30R31 47 -#define NUMCLASS 4 // XXX must always be 4 -#define MAXREGS 48 - -#define RSTATUS \ - 0, 0, SAREG|TEMPREG, SAREG|TEMPREG, \ - SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ - SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG, \ - SAREG, SAREG, SAREG, SAREG, \ - SAREG, SAREG, SAREG, SAREG, \ - SAREG, SAREG, SAREG, SAREG, \ - SAREG, SAREG, SAREG, SAREG, \ - SAREG, SAREG, SAREG, SAREG, \ - \ - SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ - SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ +#define F0 48 // scratch register +#define F1 49 // return value 0 / argument 0 +#define F2 50 // return value 1 / argument 1 +#define F3 51 // return value 2 / argument 2 +#define F4 52 // return value 3 / argument 3 +#define F5 53 // argument 4 +#define F6 54 // argument 5 +#define F7 55 // argument 6 +#define F8 56 // argument 7 +#define F9 57 // argument 8 +#define F10 58 // argument 9 +#define F11 59 // argument 10 +#define F12 60 // argument 11 +#define F13 61 // argument 12 +#define F14 62 +#define F15 63 +#define F16 64 +#define F17 65 +#define F18 66 +#define F19 67 +#define F20 68 +#define F21 69 +#define F22 70 +#define F23 71 +#define F24 72 +#define F25 73 +#define F26 74 +#define F27 75 +#define F28 76 +#define F29 77 +#define F30 78 +#define F31 79 + +#define NUMCLASS 3 +#define MAXREGS 64 // XXX cannot have more than 64 + +#define RSTATUS \ + 0, /* R0 */ \ + 0, /* R1 */ \ + SAREG|TEMPREG, /* R2 */ \ + SAREG|TEMPREG, /* R3 */ \ + SAREG|TEMPREG, /* R4 */ \ + SAREG|TEMPREG, /* R5 */ \ + SAREG|TEMPREG, /* R6 */ \ + SAREG|TEMPREG, /* R7 */ \ + SAREG|TEMPREG, /* R8 */ \ + SAREG|TEMPREG, /* R9 */ \ + SAREG|TEMPREG, /* R10 */ \ + SAREG|TEMPREG, /* R11 */ \ + SAREG|TEMPREG, /* R12 */ \ + SAREG, /* R13 */ \ + SAREG, /* R14 */ \ + SAREG, /* R15 */ \ + SAREG, /* R16 */ \ + SAREG, /* R17 */ \ + SAREG, /* R18 */ \ + SAREG, /* R19 */ \ + SAREG, /* R20 */ \ + SAREG, /* R21 */ \ + SAREG, /* R22 */ \ + SAREG, /* R23 */ \ + SAREG, /* R24 */ \ + SAREG, /* R25 */ \ + SAREG, /* R26 */ \ + SAREG, /* R27 */ \ + SAREG, /* R28 */ \ + SAREG, /* R29 */ \ + SAREG, /* R30 */ \ + SAREG, /* R31 */ \ + \ + SBREG|TEMPREG, /* R3R4 */ \ + SBREG|TEMPREG, /* R4R5 */ \ + SBREG|TEMPREG, /* R5R6 */ \ + SBREG|TEMPREG, /* R6R7 */ \ + SBREG|TEMPREG, /* R7R8 */ \ + SBREG|TEMPREG, /* R8R9 */ \ + SBREG|TEMPREG, /* R9R10 */ \ \ - SBREG, SBREG, SBREG, SBREG, \ - SBREG, SBREG, SBREG, SBREG, \ - SBREG, + SBREG, /* R14R15 */ \ + SBREG, /* R16R17 */ \ + SBREG, /* R18R19 */ \ + SBREG, /* R20R21 */ \ + SBREG, /* R22R23 */ \ + SBREG, /* R24R25 */ \ + SBREG, /* R26R2k */ \ + SBREG, /* R28R29 */ \ + SBREG, /* R30R31 */ \ + \ + SCREG|TEMPREG, /* F0 */ \ + SCREG|TEMPREG, /* F1 */ \ + SCREG|TEMPREG, /* F2 */ \ + SCREG|TEMPREG, /* F3 */ \ + SCREG|TEMPREG, /* F4 */ \ + SCREG|TEMPREG, /* F5 */ \ + SCREG|TEMPREG, /* F6 */ \ + SCREG|TEMPREG, /* F7 */ \ + SCREG|TEMPREG, /* F8 */ \ + SCREG|TEMPREG, /* F9 */ \ + SCREG|TEMPREG, /* F10 */ \ + SCREG|TEMPREG, /* F11 */ \ + SCREG|TEMPREG, /* F12 */ \ + SCREG|TEMPREG, /* F13 */ \ + SCREG, /* F14 */ \ + SCREG, /* F15 */ \ #define ROVERLAP \ { -1 }, { -1 }, { -1 }, \ @@ -230,43 +318,83 @@ typedef long long OFFSZ; { R18, R19, -1 }, { R20, R21, -1 }, \ { R22, R23, -1 }, { R24, R25, -1 }, \ { R26, R27, -1 }, { R28, R29, -1 }, \ - { R30, R31, -1 }, + { R30, R31, -1 }, \ + \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + +/* + * According to the ABI documents, there isn't really a frame pointer; + * all references to data on the stack (autos and parameters) are + * indexed relative to the stack pointer. However, pcc isn't really + * capable of running in this manner, and expects a frame pointer. + */ +#define SPREG R1 /* stack pointer */ +#define FPREG R30 /* frame pointer */ +#define GOTREG R31 /* global offset table (PIC) */ -#if 0 +#ifdef FPREG +#define ARGINIT (24*8) /* # bits above fp where arguments start */ +#define AUTOINIT (8*8) /* # bits above fp where automatics start */ #define BACKAUTO /* stack grows negatively for automatics */ #define BACKTEMP /* stack grows negatively for temporaries */ -#endif - +#else #define ARGINIT (24*8) /* # bits above fp where arguments start */ #define AUTOINIT (56*8) /* # bits above fp where automatics start */ - -/* XXX - to die */ -#define FPREG R1 /* frame pointer */ -#if 0 -#define STKREG R30 /* stack pointer */ #endif /* Return a register class based on the type of the node */ -#define PCLASS(p) (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \ - (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SCREG : SAREG)) +#define PCLASS(p) (1 << gclass((p)->n_type)) -#define GCLASS(x) (x < 32 ? CLASSA : CLASSB) -#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ -#define ENCRD(x) (x) /* Encode dest reg in n_reg */ -#define ENCRA1(x) ((x) << 6) /* A1 */ -#define ENCRA2(x) ((x) << 12) /* A2 */ -#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ -#define RETREG(x) ((x) == ULONGLONG || (x) == LONGLONG ? R3R4 : R3) +#define GCLASS(x) ((x) < 32 ? CLASSA : ((x) < 48 ? CLASSB : CLASSC)) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define RETREG(x) retreg(x) int COLORMAP(int c, int *r); +int retreg(int ty); #define SHSTR (MAXSPECIAL+1) /* short struct */ #define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ #define SPCON (MAXSPECIAL+3) /* positive constant */ +int features(int f); +#define FEATURE_BIGENDIAN 0x00010000 +#define FEATURE_PIC 0x00020000 +#define FEATURE_HARDFLOAT 0x00040000 + struct stub { struct { struct stub *q_forw, *q_back; } link; char *name; }; +extern struct stub stublist; +extern struct stub nlplist; +void addstub(struct stub *list, char *name); + +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", powerpc_builtin_stdarg_start }, \ + { "__builtin_va_arg", powerpc_builtin_va_arg }, \ + { "__builtin_va_end", powerpc_builtin_va_end }, \ + { "__builtin_va_copy", powerpc_builtin_va_copy }, \ + { "__builtin_return_address", powerpc_builtin_return_address }, + +#define NODE struct node +struct node; +NODE *powerpc_builtin_stdarg_start(NODE *f, NODE *a); +NODE *powerpc_builtin_va_arg(NODE *f, NODE *a); +NODE *powerpc_builtin_va_end(NODE *f, NODE *a); +NODE *powerpc_builtin_va_copy(NODE *f, NODE *a); +NODE *powerpc_builtin_return_address(NODE *f, NODE *a); +#undef NODE -#define FIXEDSTACKSIZE 200 /* in bytes */ +#define NARGREGS 8 + +#ifdef ELFABI +#define COM " # " +#else +#define COM " ; " +#endif diff --git a/usr.bin/pcc/powerpc/order.c b/usr.bin/pcc/powerpc/order.c index 7c72c15deca..1df4bdb82af 100644 --- a/usr.bin/pcc/powerpc/order.c +++ b/usr.bin/pcc/powerpc/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.4 2007/12/22 14:05:04 stefan Exp $ */ +/* $OpenBSD: order.c,v 1.5 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -34,19 +34,26 @@ int canaddr(NODE *); -/* is it legal to make an OREG or NAME entry which has an - * offset of off, (from a register of r), if the - * resulting thing had type t */ +/* + * Check size of offset in OREG. Called by oregok() to see if an + * OREG can be generated. + * + * returns 0 if it can, 1 otherwise. + */ int notoff(TWORD t, int r, CONSZ off, char *cp) { +#if 0 + if (off >= 32767 || off <= -32768) + printf("; notoff %lld TOO BIG!\n", off); +#endif if (cp && cp[0]) return 1; - return !(off < 32768 && off > -32769); /* YES */ + return (off >= 32768 || off <= -32769); } /* - * Turn a UMUL-referenced node into OREG. - * Be careful about register classes, this is a place where classes change. + * Generate instructions for an OREG. + * Called by swmatch(). */ void offstar(NODE *p, int shape) @@ -67,59 +74,28 @@ offstar(NODE *p, int shape) /* Converted in ormake() */ return; } - /* usually for arraying indexing: */ - if (r->n_op == LS && r->n_right->n_op == ICON && - r->n_right->n_lval == 2 && p->n_op == PLUS) { - if (isreg(p->n_left) == 0) - (void)geninsn(p->n_left, INAREG); - if (isreg(r->n_left) == 0) - (void)geninsn(r->n_left, INAREG); - return; - } } (void)geninsn(p, INAREG); } /* - * Do the actual conversion of offstar-found OREGs into real OREGs. + * Unable to convert to OREG (notoff() returned failure). Output + * suitable instructions to replace OREG. */ void myormake(NODE *q) { -#if 1 - NODE *p, *r; -#endif + NODE *p; if (x2debug) printf("myormake(%p)\n", q); -#if 1 /* XXX remove this and add UMUL(SAREG) to table.c !!! */ - p = q->n_left; - if (q->n_op != OREG && p->n_op == REG) { - q->n_op = OREG; - q->n_lval = 0; - q->n_rval = p->n_rval; - tfree(p); - return; - } -#endif - -#if 1 - /* usually for array indexing */ p = q->n_left; - if (p->n_op == PLUS && (r = p->n_right)->n_op == LS && - r->n_right->n_op == ICON && r->n_right->n_lval == 2 && - p->n_left->n_op == REG && r->n_left->n_op == REG) { - if (isreg(p->n_left) == 0) - (void)geninsn(p->n_left, INAREG); - q->n_op = OREG; - q->n_lval = 0; - q->n_rval = p->n_left->n_rval; - tfree(p); - } -#endif -#if 0 + /* + * This handles failed OREGs conversions, due to the offset + * being too large for an OREG. + */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); @@ -132,8 +108,6 @@ myormake(NODE *q) q->n_rval = p->n_rval; tfree(p); } -#endif - (void)geninsn(p, INAREG); } /* @@ -186,12 +160,144 @@ setuni(NODE *p, int cookie) struct rspecial * nspecial(struct optab *q) { - if (x2debug) printf("nspecial: op=%d, visit=0x%x: %s", q->op, q->visit, q->cstring); switch (q->op) { + /* soft-float stuff */ + case RS: + case LS: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5 }, + { NRES, R3R4 }, + { 0 }, + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 }, + }; + return s; + } + + cerror("nspecial LS/RS"); + break; + + case UMINUS: + case SCONV: + if (q->lshape == SBREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SBREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SCREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, F1 }, + { NEVER, F0 }, /* stomped on */ + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SBREG && q->rshape == SCREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NEVER, F0 }, /* stomped on */ + { NRES, F1 }, + { 0 } + }; + return s; + } else { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } + + break; + + case OPLOG: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5R6 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } + + cerror("nspecial oplog"); + break; + + case PLUS: + case MINUS: + case MUL: + case DIV: + case MOD: + if (q->lshape == SBREG && + (q->ltype & (TDOUBLE|TLDOUBLE|TLONGLONG|TULONGLONG))) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5R6 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->ltype & TFLOAT) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } + + cerror("nspecial mul"); + break; + case STASG: { static struct rspecial s[] = { @@ -239,13 +345,10 @@ nspecial(struct optab *q) } /* fallthough */ - case SCONV: case UMUL: - case MINUS: case AND: case OR: case ER: - case PLUS: { static struct rspecial s[] = { { NOLEFT, R0 }, @@ -269,6 +372,7 @@ setorder(NODE *p) { return 0; /* nothing differs on x86 */ } + /* * Set registers "live" at function calls (like arguments in registers). * This is for liveness analysis of registers. @@ -276,9 +380,19 @@ setorder(NODE *p) int * livecall(NODE *p) { - static int r[] = { R3, R4, R5, R6, R7, R8, R9, R10, -1 }; + static int r[] = { R10, R9, R8, R7, R6, R5, R4, R3, R30, R31, -1 }; + int num = 1; + + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return &r[8-0]; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + num += szty(p->n_right->n_type); + num += szty(p->n_right->n_type); + + num = (num > 8 ? 8 : num); - return &r[0]; + return &r[8 - num]; } /* @@ -287,5 +401,7 @@ livecall(NODE *p) int acceptable(struct optab *op) { - return 1; + if ((op->visit & FEATURE_PIC) != 0) + return (kflag != 0); + return features(op->visit & 0xffff0000); } diff --git a/usr.bin/pcc/powerpc/table.c b/usr.bin/pcc/powerpc/table.c index a7cb0a707b3..be3cb3e3306 100644 --- a/usr.bin/pcc/powerpc/table.c +++ b/usr.bin/pcc/powerpc/table.c @@ -1,6 +1,5 @@ +/* $OpenBSD: table.c,v 1.10 2008/04/11 20:45:52 stefan Exp $ */ /*- - * $OpenBSD: table.c,v 1.9 2007/11/24 14:08:06 stefan Exp $ - * * Copyright (c) 2007 Gregory McGarry <g.mcgarry@ieee.org> * * Permission to use, copy, modify, and distribute this software for any @@ -33,14 +32,14 @@ #define TSWORD TINT|TLONG #define TWORD TUWORD|TSWORD -#ifdef ELFABI +#if defined(ELFABI) #define HA16(x) # x "@ha" #define LO16(x) # x "@l" -#define COM " # " -#else +#elif defined(MACHOABI) #define HA16(x) "ha16(" # x ")" #define LO16(x) "lo16(" # x ")" -#define COM " ; " +#else +#error undefined ABI #endif struct optab table[] = { @@ -58,71 +57,68 @@ struct optab table[] = { * Conversions of integral types */ -/* convert (u)char to (u)char */ { SCONV, INAREG, SAREG, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, 0, RLEFT, COM "convert between (u)char and (u)char\n", }, -/* convert (u)short to (u)short */ { SCONV, INAREG, SAREG, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, 0, RLEFT, COM "convert between (u)short and (u)short\n", }, -/* convert pointers to (u)int/(u)long */ { SCONV, INAREG, SAREG, TPOINT|TWORD, SAREG, TWORD, 0, RLEFT, COM "convert a pointer/word to an int\n", }, -/* convert pointers to pointers */ { SCONV, INAREG, SAREG, TPOINT, SAREG, TPOINT, 0, RLEFT, COM "convert pointers\n", }, -/* convert (u)longlong to (u)longlong */ { SCONV, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, RLEFT, COM "convert (u)longlong to (u)longlong\n", }, -/* convert char to short */ { SCONV, INAREG, SAREG, TCHAR, SAREG, TSHORT|TSWORD, NASL|NAREG, RESC1, " extsb A1,AL" COM "convert char to short/int\n", }, -/* convert uchar to short */ { SCONV, INAREG, SAREG, TUCHAR, SAREG, TSHORT|TSWORD, - NASL|NAREG, RESC1, + 0, RLEFT, COM "convert uchar to short/int\n", }, -/* convert uchar to ushort/uint/ulong */ { SCONV, INAREG, SAREG, TUCHAR, SAREG, TUSHORT|TUWORD, - 0, RLEFT, - COM "convert uchar (AL) to ushort/unsigned (A1)\n", }, + 0, RLEFT, + COM "convert uchar to ushort/unsigned\n", }, /* XXX is this necessary? */ -/* convert char to ushort/uint/ulong */ { SCONV, INAREG, SAREG, TCHAR, SAREG, TUSHORT|TUWORD, - NASL|NAREG|NSPECIAL, RESC1, - " extsb A1,AL" COM "convert char (AL) to ushort/unsigned (A1)\n", }, + NSPECIAL|NAREG|NASL, RESC1, + " extsb A1,AL" COM "convert char to ushort/unsigned\n", }, + +{ SCONV, INBREG | FEATURE_BIGENDIAN, + SAREG, TUCHAR|TUSHORT|TUNSIGNED, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mr U1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" + " li A1,0\n", }, -/* convert uchar/ushort/uint to (u)longlong */ { SCONV, INBREG, SAREG, TUCHAR|TUSHORT|TUNSIGNED, SBREG, TLONGLONG|TULONGLONG, @@ -130,7 +126,13 @@ struct optab table[] = { " mr A1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" " li U1,0\n", }, -/* convert char/short/int to (u)longlong */ +{ SCONV, INBREG | FEATURE_BIGENDIAN, + SAREG, TCHAR|TSHORT|TSWORD, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + " mr U1,AL" COM "convert char/short/int to ulonglong\n" + " srawi A1,AL,31\n", }, + { SCONV, INBREG, SAREG, TCHAR|TSHORT|TSWORD, SBREG, TULONGLONG|TLONGLONG, @@ -138,7 +140,6 @@ struct optab table[] = { " mr A1,AL" COM "convert char/short/int to ulonglong\n" " srawi U1,AL,31\n", }, -/* convert (u)short to (u)char */ { SCONV, INAREG, SAREG, TSHORT|TUSHORT, SAREG, TCHAR|TUCHAR, @@ -146,49 +147,42 @@ struct optab table[] = { " andi. A1,AL,255" COM "convert (u)short to (u)char\n", }, /* XXX is this really necessary? */ -/* convert short to (u)int */ { SCONV, INAREG, SAREG, TSHORT, SAREG, TWORD, NAREG|NASL, RESC1, " extsh A1,AL" COM "convert short to int\n", }, -/* convert ushort to (u)int. */ { SCONV, INAREG, SAREG, TUSHORT, SAREG, TWORD, - NASL|NAREG|NSPECIAL, RESC1, + NSPECIAL|NAREG|NASL, RESC1, COM "convert ushort to word\n", }, -/* convert (u)int to (u)char */ { SCONV, INAREG, SAREG, TWORD, SAREG, TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " andi. A1,AL,255" COM "convert (u)int to (u)char\n", }, -/* convert (u)int to (u)short */ { SCONV, INAREG, SAREG, TWORD, SAREG, TSHORT|TUSHORT, NAREG|NASL|NSPECIAL, RESC1, " andi. A1,AL,65535" COM "convert (u)int to (u)short\n", }, -/* convert (u)longlong to (u)char */ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TCHAR|TUCHAR, NAREG|NSPECIAL, RESC1, " andi. A1,AL,255" COM "(u)longlong to (u)char\n", }, -/* convert (u)longlong to (u)short*/ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RESC1, " andi. A1,AL,65535" COM "(u)longlong to (u)short\n", }, -/* convert (u)longlong to (u)int */ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TWORD, @@ -197,7 +191,6 @@ struct optab table[] = { /* conversions on load from memory */ -/* char */ { SCONV, INAREG, SOREG, TCHAR, SAREG, TWORD, @@ -205,28 +198,24 @@ struct optab table[] = { " lbz A1,AL" COM "convert char to int/long\n" " extsb A1,A1\n", }, -/* uchar */ { SCONV, INAREG, SOREG, TUCHAR, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "convert uchar to int/long\n", }, -/* short */ { SCONV, INAREG, SOREG, TSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lha A1,AL" COM "convert short to int/long\n", }, -/* ushort */ { SCONV, INAREG, SOREG, TUSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lhz A1,AL" COM "convert ushort to int/long\n", }, -/* (u)longlong to (u)char */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TCHAR|TUCHAR, @@ -234,7 +223,6 @@ struct optab table[] = { " lwz A1,AL" COM "(u)longlong to (u)char\n" " andi. A1,A1,255\n", }, -/* (u)longlong to (u)short */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TSHORT|TUSHORT, @@ -242,91 +230,283 @@ struct optab table[] = { " lwz A1,AL" COM "(u)longlong to (u)short\n" " andi. A1,A1,65535\n", }, -/* (u)longlong to (u)int */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TWORD, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "(u)longlong to (u)int\n", }, -/* XXX where are the other OREG conversions? endianness problems? */ +/* + * floating-point conversions + * + * There doesn't appear to be an instruction to move values between + * the floating-point registers and the general-purpose registers. + * So values are bounced into memory... + */ + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert float to (l)double\n", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + " frsp A1,AL" COM "convert (l)double to float\n", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double\n", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double (soft-float)\n", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SAREG, TWORD, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + 2*NCREG|NAREG, RESC3, + "ZC", }, + +/* soft-float */ +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INAREG | FEATURE_HARDFLOAT, + SOREG, TFLOAT|TDOUBLE|TLDOUBLE, + SAREG, TWORD, + 2*NCREG|NAREG, RESC1, + "ZC", }, + +/* soft-float */ +{ SCONV, INAREG, + SAREG, TFLOAT, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NSPECIAL|NCREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INBREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, /* * Subroutine calls. */ { CALL, FOREFF, - SCON|SNAME, TANY, - SANY, TANY, + SCON, TANY, + SANY, TANY, 0, 0, - " bl CL" COM "call (args, no result) to scon/sname (CL)\n", }, + " bl CL" COM "call (args, no result) to scon\n", }, { UCALL, FOREFF, - SCON|SNAME, TANY, - SANY, TANY, + SCON, TANY, + SANY, TANY, 0, 0, - " bl CL" COM "call (no args, no result) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, no result) to scon\n", }, { CALL, INAREG, - SCON|SNAME, TANY, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT, + SCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, /* should be 0 */ - " bl CL" COM "call (args, result in r3) to scon/sname (CL)\n", }, + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, { CALL, INBREG, - SCON|SNAME, TANY, - SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, /* should be 0 */ - " bl CL" COM "call (args, result in r3:r4) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INCREG | FEATURE_HARDFLOAT, + SCON, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INCREG | FEATURE_HARDFLOAT, + SCON, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TFLOAT, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, { UCALL, INAREG, - SCON|SNAME, TANY, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT, + SCON, TANY, + SAREG, TFLOAT, NAREG|NASL, RESC1, /* should be 0 */ - " bl CL" COM "call (no args, result in r3) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TDOUBLE|TLDOUBLE, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, { UCALL, INBREG, - SCON|SNAME, TANY, - SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + SBREG, TDOUBLE|TLDOUBLE, NBREG|NBSL, RESC1, /* should be 0 */ - " bl CL" COM "call (no args, result in r3:r4) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, result) to scon\n", }, + + + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mtctr AL" COM "call (args, no result) to reg\n" + " bctrl\n", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mtctr AL" COM "call (no args, no result) to reg\n" + " bctrl\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" COM "call (args, result) to reg\n" + " bctrl\n", }, + +{ UCALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" COM "call (no args, result) to reg\n" + " bctrl\n", }, /* struct return */ { USTCALL, FOREFF, SCON, TANY, SANY, TANY, - NAREG|NASL, 0, - "ZP call CL\n", }, + 0, 0, + " bl CL\n", }, { USTCALL, INAREG, SCON, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ - "ZP call CL\n", }, + " bl CL\n", }, { USTCALL, INAREG, - SNAME|SAREG, TANY, - SANY, TANY, - NAREG|NASL, RESC1, /* should be 0 */ - "ZP call *AL\n", }, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" + " bctrl\n", }, { STCALL, FOREFF, SCON, TANY, SANY, TANY, - NAREG|NASL, 0, - "ZP call CL\n", }, + 0, 0, + " bl CL\n", }, { STCALL, INAREG, SCON, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ - "ZP call CL\n", }, + " bl CL\n", }, { STCALL, INAREG, - SNAME|SAREG, TANY, - SANY, TANY, - NAREG|NASL, RESC1, /* should be 0 */ - "ZP call *AL\n", }, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " mtctr AL" + " bctrl\n", }, /* * The next rules handle all binop-style operators. @@ -334,14 +514,14 @@ struct optab table[] = { /* XXX AL cannot be R0 */ { PLUS, INAREG, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " addi A1,AL,AR" COM "addition of constant\n", }, /* XXX AL cannot be R0 */ { PLUS, INAREG|FORCC, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " addic. A1,AL,AR" COM "addition of constant\n", }, @@ -354,14 +534,14 @@ struct optab table[] = { " addze U1,UL\n", }, { PLUS, INAREG, - SAREG, TWORD|TPOINT, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " add A1,AL,AR\n", }, { PLUS, INAREG|FORCC, - SAREG, TWORD|TPOINT, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " add. A1,AL,AR\n", }, @@ -372,14 +552,39 @@ struct optab table[] = { " addc A1,AL,AR" COM "64-bit add\n" " adde U1,UL,UR\n", }, +{ PLUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fadds A1,AL,AR" COM "float add\n", }, + +{ PLUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ PLUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " fadd A1,AL,AR" COM "(l)double add\n", }, + +/* soft-float */ +{ PLUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG|NBSL, RESC1, + "ZF", }, + { MINUS, INAREG, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " addi A1,AL,-AR\n", }, { MINUS, INAREG|FORCC, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " addic. A1,AL,-AR\n", }, @@ -392,14 +597,14 @@ struct optab table[] = { " addme U1,UL\n", }, { MINUS, INAREG, - SAREG, TWORD|TPOINT, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " subf A1,AR,AL\n", }, { MINUS, INAREG|FORCC, - SAREG, TWORD|TPOINT, - SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " subf. A1,AR,AL\n", }, @@ -410,6 +615,32 @@ struct optab table[] = { " subfc A1,AR,AL" COM "64-bit subtraction\n" " subfe U1,UR,UL\n", }, +{ MINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fsubs A1,AL,AR\n", }, + +{ MINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " fsub A1,AL,AR" COM "(l)double sub\n", }, + +/* soft-float */ +{ MINUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG|NBSL, RESC1, + "ZF", }, + + /* * The next rules handle all shift operators. */ @@ -442,68 +673,100 @@ struct optab table[] = { SBREG, TLONGLONG|TULONGLONG, SCON, TANY, NBREG, RESC1, - "ZO" }, + "ZO", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE", }, { RS, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " srw A1,AL,AR" COM "right shift\n", }, -{ RS, INAREG|FORCC, +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sraw A1,AL,AR" COM "arithmetic right shift\n", }, + +{ RS, INAREG|FORCC, + SAREG, TUWORD|TUSHORT|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " srw. A1,AL,AR" COM "right shift\n", }, -{ RS, INAREG, +{ RS, INAREG|FORCC, + SAREG, TSWORD|TSHORT|TCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sraw. A1,AL,AR" COM "arithmetic right shift\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " srwi A1,AL,AR" COM "right shift by constant\n", }, +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srawi A1,AL,AR" COM "arithmetic right shift by constant\n", }, + { RS, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " srwi. A1,AL,AR" COM "right shift by constant\n", }, +{ RS, INAREG|FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srawi. A1,AL,AR" COM "right shift by constant\n", }, + { RS, INBREG, SBREG, TLONGLONG|TULONGLONG, SCON, TANY, NBREG, RESC1, "ZO" }, +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE", }, + /* * The next rules takes care of assignments. "=". */ -/* assign 16-bit constant to register */ { ASSIGN, FOREFF|INAREG, - SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, 0, RDEST, " li AL,AR\n", }, -/* assign 16-bit constant to register */ { ASSIGN, FOREFF|INBREG, - SBREG, TANY, + SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, 0, RDEST, " li AL,AR\n" " li UL,UR\n", }, -/* assign constant to register */ { ASSIGN, FOREFF|INAREG, - SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, 0, RDEST, " lis AL," HA16(AR) "\n" " addi AL,AL," LO16(AR) "\n", }, -/* assign constant to register */ { ASSIGN, FOREFF|INBREG, - SBREG, TANY, + SBREG, TLONGLONG|TULONGLONG, SCON, TANY, 0, RDEST, " lis AL," HA16(AR) "\n" @@ -511,14 +774,12 @@ struct optab table[] = { " lis UL," HA16(UR) "\n"\ " addi UL,UL," LO16(UR) "\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TWORD|TPOINT, NSPECIAL, RDEST, - " lwz AL,AR\n", }, + " lwz AL,AR" COM "assign oreg to reg\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SNAME, TWORD|TPOINT, @@ -526,7 +787,6 @@ struct optab table[] = { " lis AL," HA16(AR) COM "assign sname to reg\n" " lwz AL," LO16(AR) "(AL)\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TLONGLONG|TULONGLONG, @@ -543,7 +803,6 @@ struct optab table[] = { " lis UL," HA16(UR) "\n" " lwz UL," LO16(UR) "(UL)\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TSWORD, @@ -551,22 +810,19 @@ struct optab table[] = { " lwz AL,AR" COM "load int/pointer into llong\n" " srawi UL,AR,31\n" }, -/* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TUNSIGNED|TPOINT, NSPECIAL, RDEST, " lwz AL,AR" COM "load uint/pointer into (u)llong\n" - " li UL, 0\n" }, + " li UL,0\n" }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TUCHAR, SOREG, TUCHAR, NSPECIAL, RDEST, " lbz AL,AR\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TUCHAR, SNAME, TUCHAR, @@ -574,7 +830,6 @@ struct optab table[] = { " lis AL," HA16(AR) COM "assign uchar sname to reg\n" " lbz AL," LO16(AR) "(AL)\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TCHAR, SOREG, TCHAR, @@ -582,7 +837,6 @@ struct optab table[] = { " lbz AL,AR\n" " extsb AL,AL\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TCHAR, SNAME, TCHAR, @@ -591,21 +845,18 @@ struct optab table[] = { " lbz AL," LO16(AR) "(AL)\n" " extsb AL,AL\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TSHORT, NSPECIAL, RDEST, " lha AL,AR\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TUSHORT, NSPECIAL, RDEST, " lhz AL,AR\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD, SNAME, TSHORT, @@ -613,7 +864,6 @@ struct optab table[] = { " lis AL," HA16(AR) "\n" " lha AL," LO16(AR) "(AL)\n", }, -/* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD, SNAME, TUSHORT, @@ -621,14 +871,12 @@ struct optab table[] = { " lis AL," HA16(AR) "\n" " lhz AL," LO16(AR) "(AL)\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NSPECIAL, RDEST, " stw AR,AL\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TWORD|TPOINT, SAREG, TWORD|TPOINT, @@ -636,7 +884,6 @@ struct optab table[] = { " lis A1," HA16(AL) COM "assign reg to sname\n" " stw AR," LO16(AL) "(A1)\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INBREG, SOREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, @@ -644,7 +891,6 @@ struct optab table[] = { " stw AR,AL" COM "store 64-bit value\n" " stw UR,UL\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INBREG, SNAME, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, @@ -654,14 +900,12 @@ struct optab table[] = { " lis U1," HA16(UL) "\n" " stw UR," LO16(UL) "(U1)\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, NSPECIAL, RDEST, " stb AR,AL\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, @@ -669,14 +913,12 @@ struct optab table[] = { " lis A1," HA16(AL) "\n" " stb AR," LO16(AL) "(A1)\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, NSPECIAL, RDEST, " sth AR,AL\n", }, -/* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, @@ -684,7 +926,6 @@ struct optab table[] = { " lis A1," HA16(AL) "\n" " sth AR," LO16(AL) "(A1)\n", }, -/* assign register to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, @@ -698,88 +939,280 @@ struct optab table[] = { " mr AL,AR" COM "assign UR:AR to UL:AL\n" " mr UL,UR\n", }, -#if 0 -/* assign register to memory */ -{ ASSIGN, FOREFF, - SAREG, TPOINT, - SAREG, TWORD, +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SAREG, TANY, + 3*NAREG, RDEST, + " lis A3," HA16(M) COM "bit-field assignment\n" + " addi A3,A3," LO16(M) "\n" + " lwz A2,AL\n" + " slwi A1,AR,H\n" + " and A1,A1,A3\n" + " not A3,A3\n" + " and A2,A2,A3\n" + " or A2,A2,A1\n" + " stw A2,AL\n" + "F mr AD,AR\n" + "F slwi AD,AD,32-S\n" + "F srwi AD,AD,32-S\n", }, + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RRIGHT, + "ZQ", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SOREG, TFLOAT, + SCREG, TFLOAT, 0, RDEST, - " stw AR,0(AL)" COM "indirect assign\n", }, -#endif + " stfs AR,AL" COM "store float\n", }, -#if 0 +/* soft-float */ { ASSIGN, FOREFF|INAREG, - SFLD, TANY, - SAREG, TANY, + SOREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " stw AR,AL" COM "store float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SNAME, TFLOAT, + SCREG, TFLOAT, NAREG, RDEST, - "ZE", }, + " lis A1," HA16(AL) "\n" + " stfs AR," LO16(AL) "(A1)\n", }, -{ ASSIGN, FOREFF, - SFLD, TANY, - SAREG, TANY, - NAREG, 0, - "ZE", }, -#endif +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SNAME, TFLOAT, + SAREG, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stw AR," LO16(AL) "(A1)\n", }, -/* Do not generate memcpy if return from funcall */ -#if 0 -{ STASG, INAREG|FOREFF, - SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, - SFUNCALL, TPTRTO|TSTRUCT, - 0, RRIGHT, - "", }, -#endif +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + " lfs AL,AR" COM "load float\n", }, -{ STASG, INAREG|FOREFF, - SOREG, TANY, - SAREG, TPTRTO|TANY, - NSPECIAL, RRIGHT, - "ZQ", }, +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + " lwz AL,AR" COM "load float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SNAME, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lfs AL," LO16(AR) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SNAME, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lwz AL," LO16(AR) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " fmr AL,AR" COM "assign AR to AL\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " mr AL,AR" COM "assign AR to AL\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SOREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " stfd AR,AL" COM "store (l)double\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SOREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " stw AR,AL" COM "store (l)double (soft-float)\n" + " stw UR,UL\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SNAME, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stfd AR," LO16(AL) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SNAME, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stw AR," LO16(AL) "(A1)\n" + " lis A1," HA16(UL) "\n" + " stw UR," LO16(UL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " lfd AL,AR" COM "load (l)double\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " lwz AL,AR" COM "load (l)double (soft-float)\n" + " lwz UL,UR\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SNAME, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lfd AL," LO16(AR) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SNAME, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lwz AL," LO16(AR) "(A1)\n" + " lis A1," HA16(UR) "\n" + " lwz UL," LO16(UR) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " fmr AL,AR" COM "assign AR to AL\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " mr AL,AR" COM "assign AR to AL\n" + " mr UL,UR\n", }, /* * DIV/MOD/MUL */ { DIV, INAREG, - SAREG, TSWORD, - SAREG, TWORD, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, NAREG|NASL, RESC1, - " divw A1,AL,AR\n", }, + " divwu A1,AL,AR\n", }, + +{ DIV, INAREG|FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NAREG|NASL, RESC1|RESCC, + " divwu. A1,AL,AR\n", }, { DIV, INAREG, - SAREG, TUWORD|TPOINT, - SAREG, TUWORD|TPOINT, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, NAREG|NASL, RESC1, - " divwu A1,AL,AR\n", }, + " divw A1,AL,AR\n", }, + +{ DIV, INAREG|FORCC, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, + NAREG|NASL, RESC1|RESCC, + " divw. A1,AL,AR\n", }, + +{ DIV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ DIV, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSR, RESC1, + " fdivs A1,AL,AR" COM "float divide\n", }, + +/* soft-float */ +{ DIV, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ DIV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSR, RESC1, + " fdiv A1,AL,AR" COM "(l)double divide\n", }, + +/* soft-float */ +{ DIV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, { MOD, INAREG, - SAREG, TSWORD, - SAREG, TSWORD, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, NAREG, RESC1, - " divw A1,AL,AR" COM "signed modulo\n" + " divwu A1,AL,AR" COM "unsigned modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, { MOD, INAREG, - SAREG, TWORD|TPOINT, - SAREG, TUWORD|TPOINT, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, NAREG, RESC1, - " divwu A1,AL,AR" COM "unsigned modulo\n" + " divw A1,AL,AR" COM "signed modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, +{ MOD, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + { MUL, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL, RESC1, " mulli A1,AL,AR\n", }, +{ MUL, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL, RESC1|RESCC, + " mulli. A1,AL,AR\n", }, + { MUL, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " mullw A1,AL,AR\n", }, +{ MUL, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1|RESCC, + " mullw. A1,AL,AR\n", }, + { MUL, INBREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, @@ -794,49 +1227,106 @@ struct optab table[] = { " mullw A1,AL,AR\n" " mulhw U1,AL,AR\n", }, +{ MUL, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSR, RESC1, + " fmuls A1,AL,AR" COM "float multiply\n", }, + +/* soft-float */ +{ MUL, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MUL, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSR, RESC1, + " fmul A1,AL,AR" COM "(l)double multiply\n", }, + +/* soft-float */ +{ MUL, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + /* * Indirection operators. */ { UMUL, INAREG, SANY, TANY, - SOREG, TWORD|TPOINT, + SOREG|SNAME, TWORD|TPOINT, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "word load\n", }, { UMUL, INAREG, SANY, TANY, - SOREG, TCHAR, + SOREG|SNAME, TCHAR, NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "char load\n" " extsb A1,A1\n", }, { UMUL, INAREG, SANY, TANY, - SOREG, TUCHAR, + SOREG|SNAME, TUCHAR, NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "uchar load\n", }, { UMUL, INAREG, SANY, TANY, - SOREG, TSHORT, + SOREG|SNAME, TSHORT, NAREG|NSPECIAL, RESC1, " lha A1,AL" COM "short load\n", }, { UMUL, INAREG, SANY, TANY, - SOREG, TUSHORT, + SOREG|SNAME, TUSHORT, NAREG|NSPECIAL, RESC1, " lhz A1,AL" COM "ushort load\n", }, { UMUL, INBREG, SANY, TANY, - SOREG, TLONGLONG|TULONGLONG, - NBREG, RESC1, + SOREG|SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, " lwz A1,AL" COM "64-bit load\n" " lwz U1,UL\n", }, -/* XXX UMUL of SNAME and AREG !!! */ +{ UMUL, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + " lfs A1,AL" COM "float load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, + " lwz A1,AL" COM "float load (soft-float)\n", }, + +{ UMUL, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG|SNAME, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " lfd A1,AL" COM "(l)double load\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + " lwz A1,AL" COM "(l)double load (soft-float)\n" + " lwz U1,UL\n", }, + +#if 0 +{ UMUL, INAREG, + SANY, TANY, + SAREG, TWORD|TPOINT, + NAREG, RESC1, + " lwz A1,(AL)" COM "word load\n", }, +#endif /* * Logical/branching operators @@ -865,8 +1355,8 @@ struct optab table[] = { /* compare with register */ { OPLOG, FORCC, - SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, - SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, 0, RESCC, " cmplw AL,AR\n", }, @@ -874,9 +1364,30 @@ struct optab table[] = { { OPLOG, FORCC, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, - 0, 0, + 0, RESCC, "ZD", }, +/* compare with register */ +{ OPLOG, FORCC | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RESCC, + " fcmpu 0,AL,AR\n", }, + +/* soft-float */ +{ OPLOG, FORCC, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL, RESCC, + "ZF\n", }, + +/* soft-float */ +{ OPLOG, FORCC, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL, RESCC, + "ZF", }, + { OPLOG, FORCC, SANY, TANY, SANY, TANY, @@ -885,20 +1396,20 @@ struct optab table[] = { /* AND/OR/ER */ { AND, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " and A1,AL,AR\n", }, { AND, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " and. A1,AL,AR\n", }, /* AR must be positive */ { AND, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SPCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " andi. A1,AL,AR\n", }, @@ -918,27 +1429,27 @@ struct optab table[] = { " li U1,0\n" }, { OR, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " or A1,AL,AR\n", }, { OR, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " or. A1,AL,AR\n", }, { OR, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, - SSCON, TANY, - NAREG|NASL|NSPECIAL, RESC1, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL, RESC1, " ori A1,AL,AR\n", }, { OR, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, - SSCON, TANY, - NAREG|NASL|NSPECIAL, RESC1|RESCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL, RESC1|RESCC, " ori. A1,AL,AR\n", }, { OR, INBREG, @@ -950,37 +1461,37 @@ struct optab table[] = { { OR, INBREG, SBREG, TLONGLONG|TULONGLONG, - SSCON, TANY, + SPCON, TANY, NBREG|NBSL, RESC1, " ori A1,AL,AR" COM "64-bit or with constant\n" }, { OR, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, - SSCON, TANY, + SPCON, TANY, NBREG|NBSL, RESC1|RESCC, " ori. A1,AL,AR" COM "64-bit or with constant\n" }, { ER, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " xor A1,AL,AR\n", }, { ER, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " xor. A1,AL,AR\n", }, { ER, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, - SSCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " xori A1,AL,AR\n", }, { ER, INAREG|FORCC, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, - SSCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " xori. A1,AL,AR\n", }, @@ -993,13 +1504,13 @@ struct optab table[] = { { ER, INBREG, SBREG, TLONGLONG|TULONGLONG, - SSCON, TANY, + SPCON, TANY, NBREG|NBSL, RESC1, " xori A1,AL,AR" COM "64-bit xor with constant\n" }, { ER, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, - SSCON, TANY, + SPCON, TANY, NBREG|NBSL, RESC1|RESCC, " xori. A1,AL,AR" COM "64-bit xor with constant\n" }, @@ -1023,6 +1534,14 @@ struct optab table[] = { * Convert LTYPE to reg. */ +#if defined(ELFABI) +{ OPLTYPE, INAREG | FEATURE_PIC, + SANY, TANY, + SNAME, TANY, + NAREG, RESC1, + " lwz A1,AL" COM "elfabi pic load\n", }, +#endif + { OPLTYPE, INBREG, SANY, TANY, SOREG, TLONGLONG|TULONGLONG, @@ -1039,14 +1558,12 @@ struct optab table[] = { " lis U1," HA16(UL) "\n" " lwz U1," LO16(UL) "(U1)\n", }, -/* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, - SOREG, TWORD|TPOINT, + SOREG, TWORD|TPOINT, NAREG, RESC1, " lwz A1,AL" COM "load word from memory\n", }, -/* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TWORD|TPOINT, @@ -1054,7 +1571,6 @@ struct optab table[] = { " lis A1," HA16(AL) COM "load word from sname\n" " lwz A1," LO16(AL) "(A1)\n", }, -/* load char from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TCHAR, @@ -1062,7 +1578,6 @@ struct optab table[] = { " lbz A1,AL" COM "load char from memory\n" " extsb A1,A1\n", }, -/* load char from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TCHAR, @@ -1071,14 +1586,12 @@ struct optab table[] = { " lbz A1," LO16(AL) "(A1)\n" " extsb A1,A1\n", }, -/* load uchar from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TUCHAR, NAREG, RESC1, " lbz A1,AL" COM "load uchar from memory\n", }, -/* load uchar from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TUCHAR, @@ -1093,14 +1606,12 @@ struct optab table[] = { NAREG, RESC1, " lha A1,AL" COM "load short from memory\n", }, -/* load ushort from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TUSHORT, NAREG, RESC1, " lhz A1,AL" COM "load ushort from memory\n", }, -/* load short from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TSHORT, @@ -1108,7 +1619,6 @@ struct optab table[] = { " lis A1," HA16(AL) COM "load short from sname\n" " lha A1," LO16(AL) "(A1)\n", }, -/* load ushort from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TUSHORT, @@ -1116,14 +1626,12 @@ struct optab table[] = { " lis A1," HA16(AL) COM "load ushort from sname\n" " lhz A1," LO16(AL) "(A1)\n", }, -/* load from 16-bit constant */ { OPLTYPE, INAREG, SANY, TANY, SSCON, TANY, NAREG, RESC1, " li A1,AL" COM "load 16-bit constant\n", }, -/* load from 16-bit constant */ { OPLTYPE, INBREG, SANY, TANY, SSCON, TANY, @@ -1131,15 +1639,13 @@ struct optab table[] = { " li A1,AL" COM "load 16-bit constant\n" " li U1,UL\n", }, -/* load from constant */ { OPLTYPE, INAREG, SANY, TANY, SCON, TANY, - NAREG|NASL|NSPECIAL, RESC1, + NAREG|NASL, RESC1, " lis A1," HA16(AL) COM "load constant into register\n" " addi A1,A1," LO16(AL) "\n", }, -/* load from constant */ { OPLTYPE, INBREG, SANY, TANY, SCON, TANY, @@ -1149,21 +1655,84 @@ struct optab table[] = { " lis U1," HA16(UL) "\n" " addi U1,U1," LO16(UL) "\n", }, -/* load from register */ { OPLTYPE, INAREG, SANY, TANY, SAREG, TANY, NAREG, RESC1, " mr A1,AL" COM "load AL into A1\n" }, -/* load from register */ { OPLTYPE, INBREG, SANY, TANY, - SBREG, TLONGLONG|TULONGLONG, + SBREG, TANY, NBREG, RESC1, " mr A1,AL" COM "load UL:AL into U1:A1\n" " mr U1,UL\n", }, +{ OPLTYPE, INCREG, + SANY, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " fmr A1,AL" COM "load AL into A1\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG, TFLOAT, + NCREG, RESC1, + " lfs A1,AL" COM "load float\n", }, + +/* soft-float */ +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TFLOAT, + NAREG, RESC1, + " lwz A1,AL" COM "load float (soft-float)\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SNAME, TFLOAT, + NCREG|NAREG, RESC2, + " lis A1," HA16(AL) COM "load sname\n" + " lfs A2," LO16(AL) "(A1)\n", }, + +/* soft-float */ +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TFLOAT, + NAREG, RESC1, + " lis A1," HA16(AL) COM "load sname (soft-float)\n" + " lwz A1," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " lfd A1,AL" COM "load (l)double\n", }, + +/* soft-float */ +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NBREG, RESC1, + " lwz A1,AL" COM "load (l)double (soft-float)\n" + " lwz U1,UL\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SNAME, TDOUBLE|TLDOUBLE, + NCREG|NAREG, RESC2, + " lis A1," HA16(AL) COM "load sname\n" + " lfd A2," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SNAME, TDOUBLE|TLDOUBLE, + NBREG, RESC1, + " lis A1," HA16(AL) COM "load sname (soft-float)\n" + " lwz A1," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " lwz U1," LO16(UL) "(U1)\n", }, + + /* * Negate a word. */ @@ -1181,6 +1750,25 @@ struct optab table[] = { " subfic A1,AL,0\n" " subfze U1,UL\n", }, +{ UMINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SANY, TANY, + NCREG|NCSL, RESC1, + " fneg A1,AL\n", }, + +{ UMINUS, INAREG, + SAREG, TFLOAT, + SANY, TANY, + NAREG|NASL, RESC1, + " xoris A1,AL,0x8000" COM "(soft-float)\n", }, + +{ UMINUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SANY, TANY, + NBREG|NBSL, RESC1, + " xoris U1,UL,0x8000" COM "(soft-float)\n" + " mr A1,AL\n", }, + { COMPL, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TANY, @@ -1199,48 +1787,6 @@ struct optab table[] = { */ #if 0 -{ FUNARG, FOREFF, - SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, - SANY, TWORD|TPOINT, - 0, RNULL, - " pushl AL\n", }, - -{ FUNARG, FOREFF, - SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - 0, RNULL, - " pushl AL\n", }, - -{ FUNARG, FOREFF, - SAREG|SNAME|SOREG, TSHORT, - SANY, TSHORT, - NAREG, 0, - " movswl AL,ZN\n pushl ZN\n", }, -#endif - -{ FUNARG, FOREFF, - SAREG|SNAME|SOREG, TUSHORT, - SANY, TUSHORT, - NAREG, 0, - " movzwl AL,ZN\n pushl ZN\n", }, - -#if 0 -{ FUNARG, FOREFF, - SHCH|SNAME|SOREG, TCHAR, - SANY, TCHAR, - NAREG, 0, - " movsbl AL,A1\n pushl A1\n", }, -#endif - -#if 0 -{ FUNARG, FOREFF, - SHCH|SNAME|SOREG, TUCHAR, - SANY, TUCHAR, - NAREG, 0, - " movzbl AL,A1\n pushl A1\n", }, -#endif - -#if 0 { STARG, FOREFF, SAREG|SOREG|SNAME|SCON, TANY, SANY, TSTRUCT, diff --git a/usr.bin/pcc/sparc64/code.c b/usr.bin/pcc/sparc64/code.c index 442077844b3..a22c306de66 100644 --- a/usr.bin/pcc/sparc64/code.c +++ b/usr.bin/pcc/sparc64/code.c @@ -1,3 +1,4 @@ +/* $OpenBSD: code.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -31,7 +32,16 @@ defloc(struct symtab *sp) lastloc = s; if (s == PROG) return; - printf("\t.align 4\n"); + + switch (DEUNSIGN(sp->stype)) { + case CHAR: s = 1; + case SHORT: s = 2; + case INT: + case UNSIGNED: s = 4; + default: s = 8; + } + printf("\t.align %d\n", s); + if (sp->sclass == EXTDEF) printf("\t.global %s\n", sp->soname); if (sp->slevel == 0) { @@ -52,14 +62,15 @@ efcode() void bfcode(struct symtab **sp, int cnt) { - int i; + int i, off; NODE *p, *q; struct symtab *sym; - for (i=0; i < cnt && i < I7 - I0; i++) { + /* Process the first six arguments. */ + for (i=0; i < cnt && i < 6; i++) { sym = sp[i]; q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); - q->n_rval = i + I0; + q->n_rval = RETREG_PRE(sym->stype) + i; p = tempnode(0, sym->stype, sym->sdf, sym->ssue); sym->soffset = regno(p); sym->sflags |= STNODE; @@ -67,8 +78,19 @@ bfcode(struct symtab **sp, int cnt) ecomp(p); } - if (i < cnt) - cerror("unprocessed arguments in bfcode"); /* TODO */ + /* Process the remaining arguments. */ + for (off = V9RESERVE; i < cnt; i++) { + sym = sp[i]; + spname = sym; + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + off = ALIGN(off, (tlen(p) - 1)); + sym->soffset = off * SZCHAR; + off += tlen(p); + p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); + } } void @@ -87,30 +109,55 @@ bjobcode() { } +/* + * The first six 64-bit arguments are saved in the registers O0 to O5, + * which become I0 to I5 after the "save" instruction moves the register + * window. Arguments 7 and up must be saved on the stack to %sp+BIAS+176. + * + * For a pretty picture, see Figure 3-16 in the SPARC Compliance Def 2.4. + */ static NODE * -moveargs(NODE *p, int *regp) +moveargs(NODE *p, int *regp, int *stacksize) { NODE *r, *q; if (p->n_op == CM) { - p->n_left = moveargs(p->n_left, regp); + p->n_left = moveargs(p->n_left, regp, stacksize); r = p->n_right; } else { r = p; } - if (*regp > I7 && r->n_op != STARG) - cerror("reg > I7 in moveargs"); /* TODO */ - else if (r->n_op == STARG) + /* XXX more than six FP args can and should be passed in registers. */ + if (*regp > 5 && r->n_op != STARG) { + /* We are storing the stack offset in n_rval. */ + r = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_sue); + /* Make sure we are appropriately aligned. */ + *stacksize = ALIGN(*stacksize, (tlen(r) - 1)); + r->n_rval = *stacksize; + *stacksize += tlen(r); + } else if (r->n_op == STARG) cerror("op STARG in moveargs"); - else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) - cerror("FP in moveargs"); - else if (r->n_type == FLOAT) - cerror("FP in moveargs"); else { - /* Argument can fit in O0...O7. */ q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue); - q->n_rval = (*regp)++; + + /* + * The first six non-FP arguments go in the registers O0 - O5. + * Float arguments are stored in %fp1, %fp3, ..., %fp29, %fp31. + * Double arguments are stored in %fp0, %fp2, ..., %fp28, %fp30. + * A non-fp argument still increments register, eg. + * test(int a, int b, float b) + * takes %o0, %o1, %fp5. + */ + if (q->n_type == FLOAT) + q->n_rval = F0 + (*regp++ * 2) + 1; + else if (q->n_type == DOUBLE) + q->n_rval = D0 + *regp++; + else if (q->n_type == LDOUBLE) + cerror("long double support incomplete"); + else + q->n_rval = O0 + (*regp)++; + r = buildtree(ASSIGN, q, r); } @@ -125,8 +172,51 @@ moveargs(NODE *p, int *regp) NODE * funcode(NODE *p) { - int reg = O0; - p->n_right = moveargs(p->n_right, ®); + NODE *r, *l; + int reg = 0, stacksize = 0; + + r = l = 0; + + p->n_right = moveargs(p->n_right, ®, &stacksize); + + /* + * This is a particularly gross and inefficient way to handle + * argument overflows. First, we calculate how much stack space + * we need in moveargs(). Then we assign it by moving %sp, make + * the function call, and then move %sp back. + * + * What we should be doing is getting the maximum of all the needed + * stacksize values to the prologue and doing it all in the "save" + * instruction. + */ + if (stacksize != 0) { + stacksize = V9STEP(stacksize); /* 16-bit alignment. */ + + r = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + r->n_lval = 0; + r->n_rval = SP; + r = block(MINUS, r, bcon(stacksize), INT, 0, MKSUE(INT)); + + l = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + l->n_lval = 0; + l->n_rval = SP; + r = buildtree(ASSIGN, l, r); + + p = buildtree(COMOP, r, p); + + r = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + r->n_lval = 0; + r->n_rval = SP; + r = block(PLUS, r, bcon(stacksize), INT, 0, MKSUE(INT)); + + l = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + l->n_lval = 0; + l->n_rval = SP; + r = buildtree(ASSIGN, l, r); + + p = buildtree(COMOP, p, r); + + } return p; } diff --git a/usr.bin/pcc/sparc64/local.c b/usr.bin/pcc/sparc64/local.c index a1a002933db..956013c2c99 100644 --- a/usr.bin/pcc/sparc64/local.c +++ b/usr.bin/pcc/sparc64/local.c @@ -1,3 +1,4 @@ +/* $OpenBSD: local.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -50,9 +51,11 @@ clocal(NODE *p) p = stref(block(STREF, l, r, 0, 0, 0)); } break; - case PCONV: - if (p->n_type > BTMASK && l->n_type > BTMASK) { - /* Remove unnecessary pointer conversions. */ + case PCONV: /* Remove what PCONVs we can. */ + if (l->n_op == SCONV) + break; + + if (l->n_op == ICON || (ISPTR(p->n_type) && ISPTR(l->n_type))) { l->n_type = p->n_type; l->n_qual = p->n_qual; l->n_df = p->n_df; @@ -68,7 +71,8 @@ clocal(NODE *p) (l->n_type & TMASK) == 0 && btdims[p->n_type].suesize == btdims[l->n_type].suesize) { - /* XXX: skip if FP? */ + if (p->n_type == FLOAT || p->n_type == DOUBLE) + break; l->n_type = p->n_type; nfree(p); p = l; @@ -92,12 +96,18 @@ clocal(NODE *p) case UCHAR: l->n_lval = l->n_lval & 0377; break; case SHORT: l->n_lval = (short)l->n_lval; break; case USHORT: l->n_lval = l->n_lval & 0177777; break; - case UNSIGNED: - case ULONG: l->n_lval = l->n_lval & 0xffffffff; break; - case LONG: + case UNSIGNED: l->n_lval = l->n_lval & 0xffffffff; break; case INT: l->n_lval = (int)l->n_lval; break; + case ULONG: case ULONGLONG: l->n_lval = l->n_lval; break; + case LONG: case LONGLONG: l->n_lval = (long long)l->n_lval; break; + case FLOAT: + case DOUBLE: + case LDOUBLE: + l->n_op = FCON; + l->n_dcon = l->n_lval; + break; case VOID: break; default: @@ -122,7 +132,7 @@ clocal(NODE *p) p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); - p->n_left->n_rval = I0; /* XXX adjust for float/double */ + p->n_left->n_rval = RETREG_PRE(p->n_type); break; } @@ -139,6 +149,25 @@ clocal(NODE *p) void myp2tree(NODE *p) { + struct symtab *sp; + + if (p->n_op != FCON) + return; + + sp = tmpalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->slevel = 1; + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, btdims[p->n_type].suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; } int @@ -186,7 +215,7 @@ instring(struct symtab *sp) printf("\t.ascii \""); for (s = str; *s != 0; *s++) { - if (*s == '\\') + if (*s++ == '\\') esccon(&s); if (s - str > 60) { fwrite(str, 1, s - str, stdout); @@ -211,29 +240,58 @@ infld(CONSZ off, int fsz, CONSZ val) void ninval(CONSZ off, int fsz, NODE *p) { + TWORD t; + struct symtab *sp; + union { float f; double d; int i; long long l; } u; + + t = p->n_type; + sp = p->n_sp; + + if (ISPTR(t)) + t = LONGLONG; + if (p->n_op != ICON && p->n_op != FCON) cerror("ninval: not a constant"); - if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(p->n_type) != INT) + if (p->n_op == ICON && sp != NULL && DEUNSIGN(t) != LONGLONG) cerror("ninval: not constant"); - switch (DEUNSIGN(p->n_type)) { + switch (t) { case CHAR: - printf("\t.align 1\n"); + case UCHAR: printf("\t.byte %d\n", (int)p->n_lval & 0xff); break; case SHORT: - printf("\t.align 2\n"); + case USHORT: printf("\t.half %d\n", (int)p->n_lval &0xffff); break; case BOOL: p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */ case INT: - printf("\t.align 4\n\t.long " CONFMT "\n", p->n_lval); + case UNSIGNED: + printf("\t.long " CONFMT "\n", p->n_lval); break; + case LONG: + case ULONG: case LONGLONG: - printf("\t.align 8\n\t.xword %lld\n", p->n_lval); + case ULONGLONG: + printf("\t.xword %lld", p->n_lval); + if (sp != 0) { + if ((sp->sclass == STATIC && sp->slevel > 0) + || sp->sclass == ILABEL) + printf("+" LABFMT, sp->soffset); + else + printf("+%s", exname(sp->soname)); + } + printf("\n"); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long %d\n", u.i); + break; + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.xword %lld\n", u.l); break; - /* TODO FP float and double */ } } diff --git a/usr.bin/pcc/sparc64/local2.c b/usr.bin/pcc/sparc64/local2.c index 179a7c78af5..8f7baf49cc5 100644 --- a/usr.bin/pcc/sparc64/local2.c +++ b/usr.bin/pcc/sparc64/local2.c @@ -1,3 +1,4 @@ +/* $OpenBSD: local2.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -17,13 +18,6 @@ #include "pass1.h" #include "pass2.h" -/* - * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm - * means we can use a signed 13-bit constant (simm13). This gives us a - * shortcut for small constants, instead of loading them into a register. - * Special handling is required because 13 bits lies between SSCON and SCON. - */ -#define SIMM13(val) (val < 4096 && val > -4097) char * rnames[] = { @@ -33,13 +27,16 @@ rnames[] = { "\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7", "\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7", - "\%sp", "\%fp", - "\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7", "\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15", "\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23", - "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30" + "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30", /*, "\%f31" XXX removed due to 31-element class limit */ + + "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14", + "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30", + + "\%sp", "\%fp", }; void @@ -53,22 +50,22 @@ prologue(struct interpass_prolog *ipp) { int i, stack; - /* - * SPARCv9 has a 2047 bit stack bias. Looking at output asm from gcc - * suggests this means we need a base 192 bit offset for %sp. Further - * steps need to be 8-byte aligned. - */ - stack = 192 + p2maxautooff + (p2maxautooff % 8); + stack = V9RESERVE + V9STEP(p2maxautooff); for (i=ipp->ipp_regs; i; i >>= 1) if (i & 1) - stack += 8; + stack += 16; /* TODO printf("\t.proc %d\n"); */ printf("\t.global %s\n", ipp->ipp_name); printf("\t.align 4\n"); printf("%s:\n", ipp->ipp_name); - printf("\tsave %%sp,-%d,%%sp\n", stack); + if (SIMM13(stack)) + printf("\tsave %%sp,-%d,%%sp\n", stack); + else { + printf("\tsetx -%d,%%g4,%%g1\n", stack); + printf("\tsave %%sp,%%g1,%%sp\n"); + } } void @@ -119,13 +116,15 @@ tlen(NODE *p) case SHORT: case USHORT: return (SZSHORT / SZCHAR); + case FLOAT: + return (SZFLOAT / SZCHAR); case DOUBLE: return (SZDOUBLE / SZCHAR); case INT: case UNSIGNED: + return (SZINT / SZCHAR); case LONG: case ULONG: - return (SZINT / SZCHAR); case LONGLONG: case ULONGLONG: return SZLONGLONG / SZCHAR; @@ -139,42 +138,85 @@ tlen(NODE *p) void zzzcode(NODE * p, int c) { + char *str; + NODE *l, *r; + l = p->n_left; + r = p->n_right; + switch (c) { - case 'A': /* Load constant to register. */ - if (!ISPTR(p->n_type) && SIMM13(p->n_lval)) - expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n"); - else { + case 'A': /* Add const. */ + if (ISPTR(l->n_type) && l->n_rval == FP) + r->n_lval += V9BIAS; + + if (SIMM13(r->n_lval)) + expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n"); + else + expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n" + "\tadd AL,A2,A1\n"); + break; + case 'B': /* Subtract const. */ + if (ISPTR(l->n_type) && l->n_rval == FP) + r->n_lval -= V9BIAS; + + if (SIMM13(r->n_lval)) + expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n"); + else + expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n" + "\tsub AL,A2,A1\n"); + break; + case 'C': /* Load constant to register. */ + if (ISPTR(p->n_type)) expand(p, 0, - "\tsethi %h44(AL),A1\t\t! load const\n" + "\tsethi %h44(AL),A1\t\t! load label\n" "\tor A1,%m44(AL),A1\n" "\tsllx A1,12,A1\n" "\tor A1,%l44(AL),A1\n"); - } + else if (SIMM13(p->n_lval)) + expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n"); + else + expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n"); break; - case 'B': /* Subtract const, store in temp. */ - /* - * If we are dealing with a stack location, SPARCv9 has a - * stack offset of +2047 bits. This is mostly handled by - * notoff(), but when passing as an argument this op is used. - */ - if (ISPTR(p->n_left->n_type) && p->n_left->n_rval == FP) - p->n_right->n_lval -= 2047; - - if (SIMM13(p->n_right->n_lval)) - expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const"); - else { - expand(p, 0, - "\tsethi %h44(AR),%g1\t\t! subtract const\n" - "\tor %g1,%m44(AR),%g1\n" - "\tsllx %g1,12,%g1\n" - "\tor %g1,%l44(AR),%g1\n" - "\tsub AL,%g1,A1\n"); + case 'F': /* Floating-point comparison, cf. hopcode(). */ + switch (p->n_op) { + case EQ: str = "fbe"; break; + case NE: str = "fbne"; break; + case ULE: + case LE: str = "fbule"; break; + case ULT: + case LT: str = "fbul"; break; + case UGE: + case GE: str = "fbuge"; break; + case UGT: + case GT: str = "fbug"; break; + /* XXX + 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("unknown float code: %d", p->n_op); + return; } + printf(str); + break; + + case 'Q': /* Structure assignment. */ + /* TODO Check if p->n_stsize is small and use a few ldx's + to move the struct instead of memcpy. The equiv. + could be done on all the architectures. */ + if (l->n_rval != O0) + printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]); + if (SIMM13(p->n_stsize)) + printf("\tor %%g0,%d,%%o2\n", p->n_stsize); + else + printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize); + printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n"); + printf("\tnop\n"); break; default: cerror("unknown zzzcode call: %c", c); - } } @@ -219,13 +261,10 @@ conput(FILE * fp, NODE * p) if (p->n_name[0] != '\0') { fprintf(fp, "%s", p->n_name); - if (p->n_lval < 0) { - comperr("conput: negative offset (%lld) on label %s\n", - p->n_lval, p->n_name); - return; - } + if (p->n_lval > 0) + fprintf(fp, "+"); if (p->n_lval) - fprintf(fp, "+%lld", p->n_lval); + fprintf(fp, "%lld", p->n_lval); } else fprintf(fp, CONFMT, p->n_lval); } @@ -268,9 +307,10 @@ adrput(FILE * io, NODE * p) return; case OREG: fprintf(io, "%s", rnames[p->n_rval]); - /* SPARCv9 stack bias adjustment. */ if (p->n_rval == FP) - off += 2047; + off += V9BIAS; + if (p->n_rval == SP) + off += V9BIAS + V9RESERVE; if (off > 0) fprintf(io, "+"); if (off) @@ -280,11 +320,13 @@ adrput(FILE * io, NODE * p) /* addressable value of the constant */ conput(io, p); return; - case MOVE: case REG: fputs(rnames[p->n_rval], io); return; - + case FUNARG: + /* We do something odd and store the stack offset in n_rval. */ + fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval); + return; default: comperr("bad address, %s, node %p", copst(p->n_op), p); return; @@ -320,7 +362,11 @@ rmove(int s, int d, TWORD t) int gclass(TWORD t) { - return (t == FLOAT || t == DOUBLE || t == LDOUBLE) ? CLASSC : CLASSA; + if (t == FLOAT) + return CLASSB; + if (t == DOUBLE) + return CLASSC; + return CLASSA; } void @@ -348,12 +394,17 @@ COLORMAP(int c, int *r) num += r[CLASSA]; return num < 32; case CLASSB: - return 0; + num += r[CLASSB]; + num += 2*r[CLASSC]; + return num < 32;; case CLASSC: num += r[CLASSC]; - return num < 32; + num += 2*r[CLASSB]; + return num < 17; + case CLASSD: + return 0; default: - comperr("COLORMAP: unknown class"); + comperr("COLORMAP: unknown class: %d", c); return 0; } } diff --git a/usr.bin/pcc/sparc64/macdefs.h b/usr.bin/pcc/sparc64/macdefs.h index 3e392233e61..75e4fd0cb80 100644 --- a/usr.bin/pcc/sparc64/macdefs.h +++ b/usr.bin/pcc/sparc64/macdefs.h @@ -1,3 +1,4 @@ +/* $OpenBSD: macdefs.h,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -14,6 +15,30 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* + * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm + * means we can use a signed 13-bit constant (simm13). This gives us a + * shortcut for small constants, instead of loading them into a register. + * Special handling is required because 13 bits lies between SSCON and SCON. + */ +#define SIMM13(val) (val < 4096 && val > -4097) + +/* + * The SPARCv9 ABI specifies a stack bias of 2047 bits. This means that the + * end of our call space is %fp+V9BIAS, working back towards %sp+V9BIAS+176. + */ +#define V9BIAS 2047 + +/* + * The ABI requires that every frame reserve 176 bits for saving registers + * in the case of a spill. The stack size must be 16-bit aligned. + */ +#define V9RESERVE 176 +#define V9STEP(x) ALIGN(x, 0xf) +#define ALIGN(x, y) ((x & y) ? (x + y) & ~y : x) + + #define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); #define ARGINIT (7*8) /* XXX */ @@ -26,7 +51,7 @@ #define SZFLOAT 32 #define SZDOUBLE 64 #define SZLDOUBLE 64 -#define SZLONG 32 +#define SZLONG 64 #define SZSHORT 16 #define SZLONGLONG 64 #define SZPOINT(t) 64 @@ -38,12 +63,12 @@ #define ALFLOAT 32 #define ALDOUBLE 64 #define ALLDOUBLE 64 -#define ALLONG 32 +#define ALLONG 64 #define ALLONGLONG 64 #define ALSHORT 16 -#define ALPOINT 32 +#define ALPOINT 64 #define ALSTRUCT 32 -#define ALSTACK 64 +#define ALSTACK 64 /* Min/max values. */ #define MIN_CHAR -128 @@ -55,12 +80,12 @@ #define MIN_INT -1 #define MAX_INT 0x7fffffff #define MAX_UNSIGNED 0xffffffff -#define MIN_LONG MIN_INT -#define MAX_LONG MAX_INT -#define MAX_ULONG MAX_UNSIGNED #define MIN_LONGLONG 0x8000000000000000LL #define MAX_LONGLONG 0x7fffffffffffffffLL #define MAX_ULONGLONG 0xffffffffffffffffULL +#define MIN_LONG MIN_LONGLONG +#define MAX_LONG MAX_LONGLONG +#define MAX_ULONG MAX_ULONGLONG #define BOOL_TYPE INT #define WCHAR_TYPE INT @@ -83,14 +108,15 @@ typedef long long OFFSZ; #define BYTEOFF(x) ((x)&03) #define BITOOR(x) (x) -#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \ - (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) +#define szty(t) ((ISPTR(t) || (t) == DOUBLE || \ + (t) == LONG || (t) == ULONG || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) /* Register names. */ -#define MAXREGS (31 + 2 + 31) -#define NUMCLASS 3 +#define MAXREGS (31 + 31 + 16 + 2) +#define NUMCLASS 4 //define G0 -1 #define G1 0 @@ -125,45 +151,62 @@ typedef long long OFFSZ; #define I6 29 #define I7 30 -#define SP 31 -#define FP 32 -/* -#define F0 33 -#define F1 34 -#define F2 35 -#define F3 36 -#define F4 37 -#define F5 38 -#define F6 39 -#define F7 40 -#define F8 41 -#define F9 42 -#define F10 43 -#define F11 44 -#define F12 45 -#define F13 46 -#define F14 47 -#define F15 48 -#define F16 49 -#define F17 50 -#define F18 51 -#define F19 52 -#define F20 53 -#define F21 54 -#define F22 55 -#define F23 56 -#define F24 57 -#define F25 58 -#define F26 59 -#define F27 60 -#define F28 61 -#define F29 62 -#define F30 63 -*/ +#define F0 31 +#define F1 32 +#define F2 33 +#define F3 34 +#define F4 35 +#define F5 36 +#define F6 37 +#define F7 38 +#define F8 39 +#define F9 40 +#define F10 41 +#define F11 42 +#define F12 43 +#define F13 44 +#define F14 45 +#define F15 46 +#define F16 47 +#define F17 48 +#define F18 49 +#define F19 50 +#define F20 51 +#define F21 52 +#define F22 53 +#define F23 54 +#define F24 55 +#define F25 56 +#define F26 57 +#define F27 58 +#define F28 59 +#define F29 60 +#define F30 61 +//define F31 XXX +#define D0 62 +#define D1 63 +#define D2 64 +#define D3 65 +#define D4 66 +#define D5 67 +#define D6 68 +#define D7 69 +#define D8 70 +#define D9 71 +#define D10 72 +#define D11 73 +#define D12 74 +#define D13 75 +#define D14 76 +#define D15 77 + +#define SP 78 +#define FP 79 #define FPREG FP -#define RETREG(x) ((x)==DOUBLE || (x)==LDOUBLE || (x)==FLOAT ? 33 : O0) +#define RETREG(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : O0) +#define RETREG_PRE(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : I0) #define RSTATUS \ /* global */ \ @@ -178,29 +221,48 @@ typedef long long OFFSZ; /* in */ \ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ - /* sp */ 0, \ - /* fp */ 0, \ - /* FP */ \ + /* 32-bit floating point */ \ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ - SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG /*, SBREG */ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, /*, SBREG */ \ + /* 64-bit floating point */ \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + /* sp */ SDREG, \ + /* fp */ SDREG #define ROVERLAP \ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ - { -1 }, { -1 }, \ - { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ - { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ - { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, \ - { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 }, { -1 } /*, { -1 } */ +/* 32-bit floating point */ \ + { D0, -1 }, { D0, -1 }, { D1, -1 }, { D1, -1 }, \ + { D2, -1 }, { D2, -1 }, { D3, -1 }, { D3, -1 }, \ + { D4, -1 }, { D4, -1 }, { D5, -1 }, { D5, -1 }, \ + { D6, -1 }, { D6, -1 }, { D7, -1 }, { D7, -1 }, \ + { D8, -1 }, { D8, -1 }, { D9, -1 }, { D9, -1 }, \ + { D10, -1 }, { D10, -1 }, { D11, -1 }, { D11, -1 }, \ + { D12, -1 }, { D12, -1 }, { D13, -1 }, { D13, -1 }, \ + { D14, -1 }, { D14, -1 }, { D15, -1 }, /* { D15, -1 }, */ \ +/* 64-bit floating point */ \ + { F0, F1, -1 }, { F2, F3, -1 }, { F4, F5, -1 }, \ + { F6, F7, -1 }, { F8, F9, -1 }, { F10, F11, -1 }, \ + { F12, F13, -1 }, { F14, F15, -1 }, { F16, F17, -1 }, \ + { F18, F19, -1 }, { F20, F21, -1 }, { F22, F23, -1 }, \ + { F24, F25, -1 }, { F26, F27, -1 }, { F28, F29, -1 }, \ + { F30, /* F31, */ -1 }, \ + { -1 }, \ + { -1 } -#define GCLASS(x) (x < 32 ? CLASSA : (x < 34 ? CLASSB : CLASSC)) +#define GCLASS(x) (x <= I7 ? CLASSA : \ + (x <= F30 ? CLASSB : \ + (x <= D15 ? CLASSC : \ + (x == SP || x == FP ? CLASSD : 0)))) #define PCLASS(p) (1 << gclass((p)->n_type)) -#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs XXX */ -#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int XXX */ -#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define DECRA(x,y) (((x) >> (y*7)) & 127) +#define ENCRA(x,y) ((x) << (7+y*7)) +#define ENCRD(x) (x) int COLORMAP(int c, int *r); diff --git a/usr.bin/pcc/sparc64/order.c b/usr.bin/pcc/sparc64/order.c index 271620937b0..250b67fbf36 100644 --- a/usr.bin/pcc/sparc64/order.c +++ b/usr.bin/pcc/sparc64/order.c @@ -1,3 +1,4 @@ +/* $OpenBSD: order.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -74,6 +75,19 @@ setuni(NODE *p, int cookie) struct rspecial * nspecial(struct optab *q) { + switch (q->op) { + case STASG: { + static struct rspecial s[] = { + { NEVER, O0 }, + { NRIGHT, O1 }, + { NEVER, O2 }, + { 0 } + }; + return s; + } + } + + comperr("unknown nspecial %d: %s", q - table, q->cstring); return 0; /* XXX */ } diff --git a/usr.bin/pcc/sparc64/table.c b/usr.bin/pcc/sparc64/table.c index 104ef4d3937..cfa3a7ff6c3 100644 --- a/usr.bin/pcc/sparc64/table.c +++ b/usr.bin/pcc/sparc64/table.c @@ -1,3 +1,4 @@ +/* $OpenBSD: table.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw <david@zentus.com> * @@ -16,170 +17,122 @@ #include "pass2.h" -#define TUWORD TUNSIGNED|TULONG -#define TSWORD TINT|TLONG -#define TWORD TUWORD|TSWORD +#define TS64 TLONG|TLONGLONG +#define TU64 TULONG|TULONGLONG|TPOINT +#define T64 TS64|TU64 struct optab table[] = { { -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* empty */ { PCONV, INAREG, - SAREG, TWORD|TPOINT, - SAREG, TWORD|TPOINT, + SAREG, T64, + SAREG, T64, 0, RLEFT, " ! convert between word and pointer\n", }, -/* Conversions. TODO: check zeroing on down conversions and signed/unsigned */ +/* Conversions. */ { SCONV, INAREG, - SOREG, TCHAR, - SAREG, TSWORD|TSHORT, - NAREG, RESC1, - " ldsb [AL],A1 ! int8->int16/int32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TCHAR, - SAREG, TUWORD|TUSHORT|TUCHAR, - NAREG, RESC1, - " ldub [AL],A1 ! int8 -> uint16/uint32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TUCHAR, - SAREG, TWORD|TSHORT|TUSHORT, - NAREG, RESC1, - " ldub [AL],A1 ! int8 -> (u)int16/(u)int32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TCHAR, - SAREG, TLONGLONG, - NAREG, RESC1, - " ldsb [AL],A1 ! int8 -> int64\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TUCHAR, - SAREG, TLONGLONG|TULONGLONG, - NAREG, RESC1, - " ldub [AL],A1 ! uint8 -> (u)int64\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TSHORT|TUSHORT, - SAREG, TCHAR, - NAREG, RESC1, - " ldsh [AL],A1 ! (u)int16 -> int8\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TSHORT|TUSHORT, - SAREG, TUCHAR, - NAREG, RESC1, - " ldsh [AL],A1 ! (u)int16 -> uint8\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TSHORT, - SAREG, TSWORD, - NAREG, RESC1, - " ldsh [AL],A1 ! int16 -> int32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TSHORT, - SAREG, TUWORD, - NAREG, RESC1, - " lduh [AL],A1 ! int16 -> uint32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TUSHORT, - SAREG, TWORD, - NAREG, RESC1, - " lduh [AL],A1 ! uint16 -> int32\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TSHORT, - SAREG, TLONGLONG, - NAREG, RESC1, - " ldsh [AL],A1 ! int16 -> int64\n" - " nop\n", }, + SAREG, T64|TUNSIGNED, + SAREG, TINT, + NAREG|NASL, RESC1, + " sra AL,0,A1 \t\t! (u)int64/32 -> (u)int32\n", }, { SCONV, INAREG, - SOREG, TSHORT, - SAREG, TULONGLONG, - NAREG, RESC1, - " lduh [AL],A1 ! int16 -> uint64\n" - " nop\n", }, + SAREG, T64|TINT|TUNSIGNED, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sll AL,16,A1 \t\t! (u)int64/32 -> int16\n" + " sra AL,16,A1\n" + " sra AL, 0,A1\n", }, { SCONV, INAREG, - SOREG, TUSHORT, - SAREG, TLONGLONG|TULONGLONG, - NAREG, RESC1, - " lduh [AL],A1 ! uint16 -> uint64\n" - " nop\n", }, + SAREG, T64|TINT|TUNSIGNED, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " sll AL,16,A1 \t\t! (u)int64/32 -> uint16\n" + " srl AL,16,A1\n", }, { SCONV, INAREG, - SOREG, TWORD, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT, SAREG, TCHAR, - NAREG, RESC1, - " ldsw [AL],A1 ! int32 -> int8\n" - " nop\n", }, + NAREG|NASL, RESC1, + " sll AL,24,A1 \t\t! (u)int64/32/16 -> int8\n" + " sra AL,24,A1\n" + " sra AL, 0,A1\n", }, { SCONV, INAREG, - SOREG, TWORD, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT, SAREG, TUCHAR, - NAREG, RESC1, - " lduw [AL],A1 ! int32 -> uint8\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TWORD, - SAREG, TSHORT, - NAREG, RESC1, - " ldsw [AL],A1 ! int32 -> int16\n" - " nop\n", }, - -{ SCONV, INAREG, - SOREG, TWORD, - SAREG, TUSHORT, - NAREG, RESC1, - " lduw [AL],A1 ! int32 -> uint16\n" - " nop\n", }, + NAREG|NASL, RESC1, + " and AL,0xff,A1 \t\t! (u)int64/32/16 -> uint8\n", }, { SCONV, INAREG, - SOREG, TSWORD, - SAREG, TLONGLONG|TULONGLONG, - NAREG, RESC1, - " ldsw [AL],A1 ! int32 -> (u)int64\n" - " nop\n", }, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT, + SAREG, T64, + 0, RLEFT, + " \t\t! (u)int64...8 -> (u)int64\n", }, { SCONV, INAREG, - SOREG, TUWORD, - SAREG, TLONGLONG|TULONGLONG, - NAREG, RESC1, - " lduw [AL],A1 ! int32 -> (u)int64\n" - " nop\n", }, + SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TINT, + 0, RLEFT, + " \t\t! (u)int16/8 -> int32\n", }, { SCONV, INAREG, - SOREG, TLONGLONG|TULONGLONG, - SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, - NAREG, RESC1, - " ldx [AL],A1 ! int64 -> (u)int8/16/32\n" - " nop\n", }, + SAREG, T64|TINT|TSHORT|TCHAR, + SAREG, TUNSIGNED, + 0, RLEFT, + " srl AL, 0,A1 \t\t! int32/16/8 -> uint32\n", }, -/* XXX This op is catching all register-to-register conversions. Some of these - * need special handling. */ - { SCONV, INAREG, - SAREG, TANY, - SAREG, TANY, + SAREG, TUSHORT|TUCHAR, + SAREG, TUNSIGNED, 0, RLEFT, - " \t\t! XXX in-register convert\n", }, + " \t\t! uint16/8 -> uint32\n", }, + +/* Floating-point conversions must be stored and loaded. */ + +{ SCONV, INBREG, + SOREG, T64|TUNSIGNED, + SBREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 \t\t! int64 -> float\n" + " fxtos A1,A1\n", }, + +{ SCONV, INBREG, + SOREG, TINT|TSHORT|TCHAR, + SBREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 \t\t! int32/16/8 -> float\n" + " fitos A1,A1\n", }, // XXX need 'lds', 'ldh', etc + +{ SCONV, INCREG, + SOREG, T64, + SCREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 \t\t! (u)int64 -> double\n" + " fxtod A1,A1\n", }, + +{ SCONV, INCREG, + SOREG, TINT|TSHORT|TCHAR, + SCREG, TDOUBLE, + NCREG, RESC1, + " mov AL,A1 \t\t! int32/16/8 -> double\n" + " fitod A1,A1\n", }, // XXX need 'lds' 'ldh' 'ld', etc. + +{ SCONV, INBREG, + SCREG, TDOUBLE, + SBREG, TFLOAT, + NBREG, RESC1, + " fdtos AL,A1 \t\t! double -> float\n",}, + +{ SCONV, INCREG, + SBREG, TFLOAT, + SCREG, TDOUBLE, + NCREG, RESC1, + " fstod AL,A1 \t\t! float -> double\n",}, /* Multiplication and division */ @@ -188,112 +141,205 @@ struct optab table[] = { SAREG, TANY, SAREG, TANY, NAREG|NASR|NASL, RESC1, - " mulx AL,AR,AR ! multiply\n", }, + " mulx AL,AR,A1 ! multiply\n", }, + +{ MUL, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSR|NBSL, RESC1, + " fmuls AL,AR,A1 ! multiply float\n", }, + +{ MUL, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSR|NCSL, RESC1, + " fmuld AL,AR,A1 ! multiply double\n", }, { DIV, INAREG, - SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG, - SAREG, TUWORD|TUSHORT|TUCHAR|TULONGLONG, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, NAREG|NASR|NASL, RESC1, - " udivx AL,AR,AR ! unsigned division\n", }, + " udivx AL,AR,A1 ! unsigned division\n", }, { DIV, INAREG, - SAREG, TWORD|TSHORT|TCHAR|TLONGLONG, - SAREG, TWORD|TSHORT|TCHAR|TLONGLONG, + SAREG, TINT|TSHORT|TCHAR|TS64, + SAREG, TINT|TSHORT|TCHAR|TS64, NAREG|NASR|NASL, RESC1, - " sdivx AL,AR,AR ! signed division\n", }, - - /* TODO MOD */ + " sdivx AL,AR,A1 ! signed division\n", }, + +{ DIV, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSR|NBSL, RESC1, + " fdivs AL,AR,A1 ! divide float\n", }, + +{ DIV, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSR|NCSL, RESC1, + " fdivd AL,AR,A1 ! divide double\n", }, + +{ MOD, INAREG, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + NAREG, RESC1, + " udivx AL,AR,A1 ! unsigned modulo\n" + " mulx A1,AR,A1\n" + " sub AL,A1,A1\n", }, + +{ MOD, INAREG, + SAREG, TINT|TSHORT|TCHAR|TS64, + SAREG, TINT|TSHORT|TCHAR|TS64, + NAREG, RESC1, + " sdivx AL,AR,A1 ! signed modulo\n" + " mulx A1,AR,A1\n" + " sub AL,A1,A1\n", }, { PLUS, INAREG, SAREG, TANY, SAREG, TANY, NAREG|NASL, RESC1, - " add A1,AL,AR\n", }, + " add AL,AR,A1\n", }, + +{ PLUS, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSL, RESC1, + " fadds AL,AR,A1\n", }, + +{ PLUS, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSL, RESC1, + " faddd AL,AR,A1\n", }, { PLUS, INAREG, SAREG, TANY, - SCCON, TWORD, - NAREG|NASL, RESC1, - " add AL,AR,A1 ! add constant to reg\n", }, + SCON, TANY, + (3*NAREG)|NASL, RESC1, + "ZA", }, { MINUS, INAREG, SAREG, TANY, SAREG, TANY, NAREG|NASL, RESC1, - " sub AL,AR,AR\n", }, + " sub AL,AR,A1\n", }, + +{ MINUS, INBREG, + SBREG, TANY, + SBREG, TANY, + NBREG|NBSL|NBSR, RESC1, + " fsubs AL,AR,A1\n", }, + +{ MINUS, INCREG, + SCREG, TANY, + SCREG, TANY, + NCREG|NCSL|NBSR, RESC1, + " fsubd AL,AR,A1\n", }, { MINUS, INAREG, SAREG, TANY, - SSCON, TANY, - NAREG|NASL, RESC1, - "ZB\n", }, + SCON, TANY, + (3*NAREG)|NASL, RESC1, + "ZB", }, { UMINUS, INAREG, SAREG, TANY, SANY, TANY, NAREG|NASL, RESC1, - " sub A1,AL,A1\n", }, + " sub %g0,AL,A1\n", }, + +{ UMINUS, INBREG, + SBREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, + " fsubs %g0,AL,A1\n", }, + +{ UMINUS, INCREG, + SCREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, + " fsubd %g0,AL,A1\n", }, /* Shifts */ { RS, INAREG, - SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TANY, NAREG|NASL, RESC1, - " sra AL,AR,AL ! shift right\n", }, + " sra AL,AR,A1 ! shift right\n", }, { RS, INAREG, - SAREG, TLONGLONG|TULONGLONG, + SAREG, T64, SANY, TANY, NAREG|NASL, RESC1, - " srax AL,AR,AL ! shift right\n", }, + " srax AL,AR,A1 ! shift right\n", }, { LS, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TANY, NAREG|NASL, RESC1, - " sll AL,AR,AL ! shift left\n", }, + " sll AL,AR,A1 ! shift left\n", }, { LS, INAREG, - SAREG, TLONGLONG|TULONGLONG, + SAREG, T64, SANY, TANY, NAREG|NASL, RESC1, - " sllx AL,AR,AL ! shift left\n", }, + " sllx AL,AR,A1 ! shift left\n", }, +{ COMPL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " orn AL,%g0,A1 ! complement\n", }, /* Assignments */ { ASSIGN, FOREFF|INAREG, - SOREG, TWORD, - SAREG, TWORD, + SOREG, TINT|TUNSIGNED, + SAREG, TINT|TUNSIGNED, 0, RDEST, " stw AR,[AL] ! store (u)int32\n" " nop\n", }, { ASSIGN, FOREFF|INAREG, - SOREG, TSHORT|TUSHORT, - SAREG, TSHORT|TUSHORT, + SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, 0, RDEST, " sth AR,[AL] ! store (u)int16\n" " nop\n", }, { ASSIGN, FOREFF|INAREG, - SOREG, TCHAR|TUCHAR, - SAREG, TCHAR|TUCHAR, + SOREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, 0, RDEST, " stb AR,[AL] ! store (u)int8\n" " nop\n", }, { ASSIGN, FOREFF|INAREG, - SOREG, TLONGLONG|TULONGLONG|TPOINT, - SAREG, TLONGLONG|TULONGLONG|TPOINT, + SOREG, T64, + SAREG, T64, 0, RDEST, " stx AR,[AL] ! store (u)int64\n" " nop\n", }, +{ ASSIGN, FOREFF|INBREG, + SOREG, TFLOAT, + SBREG, TFLOAT, + 0, RDEST, + " st AR,[AL] ! store float\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SOREG, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + " std AR,[AL] ! store double\n" + " nop\n", }, + { ASSIGN, FOREFF|INAREG, - SNAME, TWORD, - SAREG, TWORD, + SNAME, TINT|TUNSIGNED, + SAREG, TINT|TUNSIGNED, NAREG, RDEST, " sethi %h44(AL),A1 \t! store (u)int32 into sname\n" " or A1,%m44(AL),A1\n" @@ -322,8 +368,8 @@ struct optab table[] = { " nop\n", }, { ASSIGN, FOREFF|INAREG, - SNAME, TLONGLONG|TULONGLONG|TPOINT, - SAREG, TLONGLONG|TULONGLONG|TPOINT, + SNAME, T64, + SAREG, T64, NAREG, RDEST, " sethi %h44(AL),A1 \t! store (u)int64 into sname\n" " or A1,%m44(AL),A1\n" @@ -331,25 +377,65 @@ struct optab table[] = { " stx AR,[A1+%l44(AL)]\n" " nop\n", }, +{ ASSIGN, FOREFF|INBREG, + SNAME, TFLOAT, + SBREG, TFLOAT, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store float into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " st AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SNAME, TDOUBLE, + SCREG, TDOUBLE, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store double into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " std AR,[A1+%l44(AL)]\n" + " nop\n", }, + { ASSIGN, FOREFF|INAREG, SAREG, TANY, SAREG, TANY, 0, RDEST, - " mov AL, AR ! register move\n", }, + " mov AR,AL ! register move\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TANY, + SBREG, TANY, + 0, RDEST, + " fmovs AR,AL ! move float\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TANY, + SCREG, TANY, + 0, RDEST, + " fmovd AR,AL ! move double\n", }, + +/* Structure assignment. */ + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RRIGHT, + "ZQ", }, /* Comparisons. */ { EQ, FORCC, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TANY, + SAREG, TANY, 0, RESCC, " cmp AL,AR\n" " be LC\n" " nop\n", }, { NE, FORCC, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, - SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TANY, + SAREG, TANY, 0, RESCC, " cmp AL,AR\n" " bne LC\n" @@ -361,13 +447,15 @@ struct optab table[] = { 0, RESCC, " O AL,LC\n" " nop\n", }, + { OPLOG, FORCC, SAREG, TANY, SAREG, TANY, NAREG|NASL, RESCC, - " sub AL,AR,A1 ! oplog\n" + " sub AL,AR,A1 ! oplog\n" " O A1,LC\n" " nop\n", }, + { OPLOG, FORCC, SAREG, TANY, SCCON, TANY, @@ -376,33 +464,58 @@ struct optab table[] = { " O A1,LC\n" " nop\n", }, +{ OPLOG, FORCC, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG, RESCC, + " fcmps AL,AR ! oplog float\n" + " ZF LC\n", }, + +{ OPLOG, FORCC, + SOREG, TFLOAT, + SBREG, TFLOAT, + NBREG, RESCC, + " ld [AL], A1 ! oplog float oreg\n" + " nop\n" + " fcmps A1,AR\n" + " ZF LC\n", }, + +{ OPLOG, FORCC, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESCC, + " XXX double oplog\n", }, + /* Load constants to register. */ { OPLTYPE, INAREG, SCON, TANY, - SNAME, TLONGLONG|TULONGLONG|TPOINT, + SNAME, T64, NAREG, RESC1, " sethi %h44(AL),A1\t ! load const (u)int64 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " ldx [A1+%l44(AL)],A1\n", }, + " ldx [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, - SNAME, TWORD, + SNAME, TINT, NAREG, RESC1, " sethi %h44(AL),A1\t ! load const int32 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " ldsw [A1+%l44(AL)],A1\n", }, + " ldsw [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, - SNAME, TUWORD, + SNAME, TUNSIGNED, NAREG, RESC1, " sethi %h44(AL),A1\t! load const uint32 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " lduw [A1+%l44(AL)],A1\n", }, + " lduw [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, SNAME, TSHORT, @@ -410,7 +523,8 @@ struct optab table[] = { " sethi %h44(AL),A1\t! load const int16 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " ldsh [A1+%l44(AL)],A1\n", }, + " ldsh [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, SNAME, TUSHORT, @@ -418,7 +532,8 @@ struct optab table[] = { " sethi %h44(AL),A1\t ! load const uint16 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " lduh [A1+%l44(AL)],A1\n", }, + " lduh [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, SNAME, TCHAR, @@ -426,7 +541,8 @@ struct optab table[] = { " sethi %h44(AL),A1\t\t! load const int8 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " ldsb [A1+%l44(AL)],A1\n", }, + " ldsb [A1+%l44(AL)],A1\n" + " nop\n", }, { OPLTYPE, INAREG, SCON, TANY, SNAME, TUCHAR, @@ -434,14 +550,34 @@ struct optab table[] = { " sethi %h44(AL),A1\t! load const uint8 to reg\n" " or A1,%m44(AL),A1\n" " sllx A1,12,A1\n" - " ldub [A1+%l44(AL)],A1\n", }, + " ldub [A1+%l44(AL)],A1\n" + " nop\n", }, + +{ OPLTYPE, INBREG, + SBREG, TANY, + SNAME, TANY, + NAREG|NBREG, RESC2, + " sethi %h44(AL),A1\t! load const float to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ld [A1+%l44(AL)],A2\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SCREG, TANY, + SNAME, TANY, + NAREG|NCREG, RESC2, + " sethi %h44(AL),A1\t! load const double to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldd [A1+%l44(AL)],A2\n" + " nop\n", }, { OPLTYPE, INAREG, SANY, TANY, SCON, TANY, - NAREG, RESC1, - "ZA" }, - + (2*NAREG), RESC1, + "ZC" }, /* Convert LTYPE to reg. */ @@ -451,7 +587,7 @@ struct optab table[] = { NAREG, RESC1, " ldsb [AL],A1 ! load int8 to reg\n" " nop\n", }, - + { OPLTYPE, INAREG, SAREG, TANY, SOREG, TUCHAR, @@ -475,21 +611,21 @@ struct optab table[] = { { OPLTYPE, INAREG, SAREG, TANY, - SOREG, TWORD, + SOREG, TINT, NAREG, RESC1, " ldsw [AL],A1 ! load int32 to reg\n" " nop\n", }, { OPLTYPE, INAREG, SAREG, TANY, - SOREG, TWORD, + SOREG, TUNSIGNED, NAREG, RESC1, " lduw [AL],A1 ! load uint32 to reg\n" " nop\n", }, { OPLTYPE, INAREG, SAREG, TANY, - SOREG, TLONGLONG|TULONGLONG|TPOINT, + SOREG, T64, NAREG, RESC1, " ldx [AL],A1 ! load (u)int64 to reg\n" " nop\n", }, @@ -500,6 +636,19 @@ struct optab table[] = { NAREG, RESC1, " mov \%g0,A1\t ! load 0 to reg\n", }, +{ OPLTYPE, INBREG, + SBREG, TFLOAT, + SOREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 ! load float to reg\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SCREG, TDOUBLE, + SOREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 ! load double to reg\n" + " nop\n", }, /* Jumps. */ @@ -573,6 +722,36 @@ struct optab table[] = { " call AL ! = (*AL)(args)\n" " nop\n", }, +/* Function arguments. */ + +{ FUNARG, FOREFF, + SAREG, T64, + SANY, TANY, + 0, 0, + " stx AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TINT|TUNSIGNED, + SANY, TANY, + 0, 0, + " stw AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TSHORT|TUSHORT, + SANY, TANY, + 0, 0, + " sth AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TCHAR|TUCHAR, + SANY, TANY, + 0, 0, + " stb AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + /* Indirection. */ @@ -583,20 +762,20 @@ struct optab table[] = { " O AL,AR,A1\n", }, { UMUL, INAREG, - SANY, TLONGLONG|TULONGLONG|TPOINT, - SOREG, TLONGLONG|TULONGLONG|TPOINT, + SANY, T64, + SOREG, T64, NAREG, RESC1, " ldx [AL],A1 ! (u)int64 load\n" " nop\n", }, { UMUL, INAREG, - SANY, TWORD, - SOREG, TWORD, + SANY, TINT, + SOREG, TINT, NAREG, RESC1, " ldsw [AL],A1 ! int32 load\n" " nop\n", }, { UMUL, INAREG, - SANY, TUWORD, - SOREG, TUWORD, + SANY, TUNSIGNED, + SOREG, TUNSIGNED, NAREG, RESC1, " lduw [AL],A1 ! uint32 load\n" " nop\n", }, @@ -625,6 +804,20 @@ struct optab table[] = { " lduh [AL],A1 ! uint16 load\n" " nop\n", }, +{ UMUL, INBREG, + SANY, TFLOAT, + SOREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 ! load float\n" + " nop\n", }, + +{ UMUL, INCREG, + SANY, TDOUBLE, + SOREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 ! load double\n" + " nop\n", }, + { FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE, "ERR: printing free op\n" }, }; |