diff options
author | Stefan Kempf <stefan@cvs.openbsd.org> | 2007-12-22 14:05:05 +0000 |
---|---|---|
committer | Stefan Kempf <stefan@cvs.openbsd.org> | 2007-12-22 14:05:05 +0000 |
commit | 364275c5dd83730a39ae5a9a474e904ff4f2b27a (patch) | |
tree | 161b25b34d6705dd452dd2e03f1631c5fc020c04 /usr.bin/pcc | |
parent | 42fb310342bd3c17c926835e06388d425368bb54 (diff) |
Sync with main repo.
Diffstat (limited to 'usr.bin/pcc')
-rw-r--r-- | usr.bin/pcc/powerpc/README | 38 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/code.c | 12 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/local.c | 94 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/local2.c | 207 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/macdefs.h | 8 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/order.c | 39 |
6 files changed, 193 insertions, 205 deletions
diff --git a/usr.bin/pcc/powerpc/README b/usr.bin/pcc/powerpc/README index d81683ef881..d3c867815cb 100644 --- a/usr.bin/pcc/powerpc/README +++ b/usr.bin/pcc/powerpc/README @@ -10,13 +10,39 @@ on OS X while linking against the system libraries, use the -k option. Current issues: -- no floating point +- no floating point (need mickey's patches to support >64 registers) - mod/div on longlong not supported -- problems with static variables with PIC - the stack frame is always 200 bytes - need to calculate size and patch - OREGs to temporaries and arguments -- function arguments are always saved to the stack -- permanent registers >R13 are not saved + OREGs to temporaries and arguments [see discussion below] +- function arguments are always saved to the stack [need to change MI code] +- permanent registers >R13 are not saved [need to change MI code] - structure arguments don't work - return of structure doesn't work -- no built-in vararg support +- function pointers don't work for PIC +- constant structure assignment doesn't work properly for PIC +- no built-in vararg support [shouldn't be too hard to add] + +The way most modern CPUs create the stack is to allocate the frame +to contain room for the temporaries, to save the permanent registers +and to store the arguments to functions invoked from within the function. +To achieve this, all the information must be known when the prologue +is generated. Currently we only know the size of the temporaries - +we don't know the size of the argument space for each function that +gets invoked from this function. Even if we did know this information, +we create ops to save the register arguments (R3-R10), early in pass1 +and don't know the position of the stack pointer, and the size of the +argument space required to "step over". + +One solution is to have two pointers to the stack. One for the top +of the stack and the other pointing just below the temporaries but above +the argument space. Then our function arguments and the permanent registers can +be saved fixed-relative to this register. If we don't know the size of +argument space, we cannot "dynamically" alter the stack (like we do with mips), +since the powerpc ABI specifies that the "lowest" address +in the stack frame is the saved stack pointer (pointing to the previous +stack frame). While this is a nice feature for tracking back through the +stack frames (which mips has always had problems with), it makes it +next-to-impossible to increase the strack frame dynamically. + +I guess the best approach is to determine the size of the argument stack +and have a second frame pointer. diff --git a/usr.bin/pcc/powerpc/code.c b/usr.bin/pcc/powerpc/code.c index 0f2338da659..24291be59c6 100644 --- a/usr.bin/pcc/powerpc/code.c +++ b/usr.bin/pcc/powerpc/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.5 2007/11/22 15:06:43 stefan Exp $ */ +/* $OpenBSD: code.c,v 1.6 2007/12/22 14:05:04 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -294,16 +294,6 @@ bycode(int t, int i) } /* - * n integer words of zeros - */ -void -zecode(int n) -{ - printf(" .zero %d\n", n * (SZINT/SZCHAR)); -// inoff += n * SZINT; -} - -/* * return the alignment of field of type t */ int diff --git a/usr.bin/pcc/powerpc/local.c b/usr.bin/pcc/powerpc/local.c index 64cc3598536..76a90a122a3 100644 --- a/usr.bin/pcc/powerpc/local.c +++ b/usr.bin/pcc/powerpc/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.4 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: local.c,v 1.5 2007/12/22 14:05:04 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -163,7 +163,6 @@ clocal(NODE *p) #endif switch (o = p->n_op) { -#if 1 case ADDROF: #ifdef PCC_DEBUG if (xdebug) { @@ -183,9 +182,18 @@ clocal(NODE *p) 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; -#if 1 + /* cast to pointer-to-char before adding offset */ l = block(REG, NIL, NIL, INT, p->n_df, p->n_sue); l->n_lval = 0; @@ -193,17 +201,19 @@ clocal(NODE *p) 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; -#endif } } break; -#endif case NAME: if ((q = p->n_sp) == NULL) @@ -232,60 +242,70 @@ clocal(NODE *p) p->n_sp = q; } /* FALLTHROUGH */ -#if 1 default: if (kflag && blevel > 0 && !ISFTN(p->n_type)) { - TWORD t = p->n_type; - l = block(REG, NIL, NIL, INCREF(t), p->n_df, p->n_sue); - l->n_lval = 0; - l->n_rval = R31; + TWORD t = p->n_type; + int isextern = p->n_sp->sclass == EXTERN; + int off = 0; - p->n_op = ICON; - p->n_type = INCREF(p->n_type); + if (isextern) + t = INCREF(t); - p = block(PLUS, l, p, INCREF(t), p->n_df, p->n_sue); - p = block(UMUL, p, NIL, t, p->n_df, p->n_sue); - } -#endif + 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); + + 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); + } } break; case STCALL: case CALL: - { - /* break nested CALLs */ breaknestedcalls(p); /* Fix function call arguments. */ /* move everything into the registers */ - /* XXX have to save the old values of R3-R10 on the stack - (but only once per function */ { int reg = R3; fixupfuncargs(p->n_right, ®); } + /* FALLTHOUGH */ #if 0 - for (r = p->n_right; r->n_op == CM; r = r->n_left) { - if (r->n_right->n_op != STARG && - r->n_right->n_op != FUNARG) { - printf("HERE\n"); - r->n_right = block(FUNARG, r->n_right, NIL, - r->n_right->n_type, r->n_right->n_df, - r->n_right->n_sue); - } - } - if (r->n_op != STARG && r->n_op != FUNARG) { - printf("HERE2\n"); - l = talloc(); - *l = *r; - r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type; + 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; +#endif break; - } case CBRANCH: l = p->n_left; @@ -471,7 +491,7 @@ clocal(NODE *p) p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); p->n_left->n_rval = p->n_left->n_type == BOOL ? - RETREG(CHAR) : RETREG(p->n_type); + RETREG(BOOL_TYPE) : RETREG(p->n_type); break; case LS: @@ -665,7 +685,7 @@ zbits(OFFSZ off, int fsz) } } if (fsz >= SZCHAR) { - printf("\t.zero %d\n", fsz/SZCHAR); + printf("\t.space %d\n", fsz/SZCHAR); fsz -= (fsz/SZCHAR) * SZCHAR; } if (fsz) { diff --git a/usr.bin/pcc/powerpc/local2.c b/usr.bin/pcc/powerpc/local2.c index f0d7f7ac3a1..b7347243dc6 100644 --- a/usr.bin/pcc/powerpc/local2.c +++ b/usr.bin/pcc/powerpc/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.4 2007/11/25 12:54:09 stefan Exp $ */ +/* $OpenBSD: local2.c,v 1.5 2007/12/22 14:05:04 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -324,10 +324,10 @@ twollcomp(NODE *p) } if (p->n_op >= ULE) cb1 += 4, cb2 += 4; - expand(p, 0, " cmpl UR,UL\n"); + expand(p, 0, "\tcmplw UR,UL # compare 64-bit values (upper)\n"); if (cb1) cbgen(cb1, s); if (cb2) cbgen(cb2, e); - expand(p, 0, " cmpl AR,AL\n"); + expand(p, 0, "\tcmplw AR,AL # (and lower)\n"); cbgen(p->n_op, e); deflab(s); } @@ -505,6 +505,7 @@ zzzcode(NODE *p, int c) int pr, lr, s; char *ch; #endif + char inst[50]; switch (c) { #if 0 @@ -601,67 +602,29 @@ zzzcode(NODE *p, int c) break; #endif -#if 0 case 'Q': /* emit struct assign */ - /* XXX - optimize for small structs */ - printf("\tpushl $%d\n", p->n_stsize); - expand(p, INAREG, "\tpushl AR\n"); - expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n"); - printf("\tcall memcpy\n"); - printf("\taddl $12,%%esp\n"); - break; -#endif + if (p->n_stsize == 4) { + int sz = sizeof inst; -#if 0 - case 'S': /* emit eventual move after cast from longlong */ - pr = DECRA(p->n_reg, 0); - lr = p->n_left->n_rval; - switch (p->n_type) { - case CHAR: - case UCHAR: - if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' && - rnames[pr][1] == rnames[lr][1]) - break; - if (rnames[lr][2] == 'x') { - printf("\tmovb %%%cl,%s\n", - rnames[lr][1], rnames[pr]); - break; - } - /* Must go via stack */ - s = BITOOR(freetemp(1)); - printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s); - printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]); -// comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]); - break; - - case SHORT: - case USHORT: - if (rnames[lr][1] == rnames[pr][2] && - rnames[lr][2] == rnames[pr][3]) - break; - printf("\tmovw %%%c%c,%%%s\n", - rnames[lr][1], rnames[lr][2], rnames[pr]+2); - break; - case INT: - case UNSIGNED: - if (rnames[lr][1] == rnames[pr][2] && - rnames[lr][2] == rnames[pr][3]) - break; - printf("\tmovl %%e%c%c,%s\n", - rnames[lr][1], rnames[lr][2], rnames[pr]); - break; + 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; + } - default: - if (rnames[lr][1] == rnames[pr][2] && - rnames[lr][2] == rnames[pr][3]) - break; - comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]); - 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")); break; -#endif - default: comperr("zzzcode %c", c); } @@ -764,8 +727,12 @@ conput(FILE *fp, NODE *p) if (*s != '\0') { if (kflag && p->n_sp && ISFTN(p->n_sp->stype)) { - fprintf(fp, "%s$stub", s); - addstub(&stublist, s); + 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); @@ -1055,62 +1022,44 @@ myoptim(struct interpass *ip) #endif } -#if 0 -static char rl[] = - { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI }; -static char rh[] = - { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI }; -#endif - +/* + * Move data between registers. While basic registers aren't a problem, + * we have to handle the special case of overlapping composite registers. + * It might just be easier to modify the register allocator so that + * moves between overlapping registers isn't possible. + */ void rmove(int s, int d, TWORD t) { -#if 0 - int sl, sh, dl, dh; - switch (t) { case LONGLONG: case ULONGLONG: -#if 1 - sl = rl[s-EAXEDX]; - sh = rh[s-EAXEDX]; - dl = rl[d-EAXEDX]; - dh = rh[d-EAXEDX]; - - /* sanity checks, remove when satisfied */ - if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 || - memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0) - comperr("rmove source error"); - if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 || - memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0) - comperr("rmove dest error"); -#define SW(x,y) { int i = x; x = y; y = i; } - if (sl == dh || sh == dl) { - /* Swap if moving to itself */ - SW(sl, sh); - SW(dl, dh); + if (s == d+1) { + /* dh = sl, copy low word first */ + printf("\tmr "); + reg64name(d,0); + printf(","); + reg64name(s,0); + printf("\n"); + printf("\tmr "); + reg64name(d,1); + printf(","); + reg64name(s,1); + printf("\n"); + } else { + /* copy high word first */ + printf("\tmr "); + reg64name(d,1); + printf(","); + reg64name(s,1); + printf("\n"); + printf("\tmr "); + reg64name(d,0); + printf(","); + reg64name(s,0); + printf("\n"); } - if (sl != dl) - printf(" movl %s,%s\n", rnames[sl], rnames[dl]); - if (sh != dh) - printf(" movl %s,%s\n", rnames[sh], rnames[dh]); -#else - if (memcmp(rnames[s], rnames[d], 3) != 0) - printf(" movl %%%c%c%c,%%%c%c%c\n", - rnames[s][0],rnames[s][1],rnames[s][2], - rnames[d][0],rnames[d][1],rnames[d][2]); - if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0) - printf(" movl %%%c%c%c,%%%c%c%c\n", - rnames[s][3],rnames[s][4],rnames[s][5], - rnames[d][3],rnames[d][4],rnames[d][5]); -#endif - break; - case CHAR: - case UCHAR: - printf(" movb %s,%s\n", rnames[s], rnames[d]); break; - case FLOAT: - case DOUBLE: case LDOUBLE: #ifdef notdef /* a=b()*c(); will generate this */ @@ -1118,43 +1067,37 @@ rmove(int s, int d, TWORD t) #endif break; default: - printf(" movl %s,%s\n", rnames[s], rnames[d]); + printf("\tmr %s,%s\n", rnames[d], rnames[s]); } -#endif } /* * For class c, find worst-case displacement of the number of * registers in the array r[] indexed by class. + * + * On PowerPC, we have: + * + * 32 32-bit registers (2 reserved) + * 16 64-bit pseudo registers + * 32 floating-point registers */ int COLORMAP(int c, int *r) { - return 1; -#if 0 - int num; + int num = 0; switch (c) { case CLASSA: - num = r[CLASSB] > 4 ? 4 : r[CLASSB]; - num += 2*r[CLASSC]; num += r[CLASSA]; - return num < 6; + num += 2*r[CLASSB]; + return num < 30; case CLASSB: - num = r[CLASSA]; - num += 2*r[CLASSC]; - num += r[CLASSB]; - return num < 4; - case CLASSC: - num = r[CLASSA]; - num += r[CLASSB] > 4 ? 4 : r[CLASSB]; - num += 2*r[CLASSC]; - return num < 5; - case CLASSD: - return r[CLASSD] < DREGCNT; + num += 2*r[CLASSB]; + num += r[CLASSA]; + return num < 16; } + assert(0); return 0; /* XXX gcc */ -#endif } #ifdef ELFABI @@ -1237,3 +1180,11 @@ special(NODE *p, int shape) } return SRNOPE; } + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} diff --git a/usr.bin/pcc/powerpc/macdefs.h b/usr.bin/pcc/powerpc/macdefs.h index 4e4406428a6..8f9f3746f09 100644 --- a/usr.bin/pcc/powerpc/macdefs.h +++ b/usr.bin/pcc/powerpc/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.2 2007/11/01 10:52:58 otto Exp $ */ +/* $OpenBSD: macdefs.h,v 1.3 2007/12/22 14:05:04 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -107,8 +107,6 @@ typedef long long OFFSZ; #define STABLBL "LL%d" /* format for stab (debugging) labels */ #define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ -#define MYP2TREE(p) myp2tree(p); - #undef FIELDOPS /* no bit-field instructions */ #if 0 #define RTOLBYTES /* bytes are numbered right to left */ @@ -262,10 +260,6 @@ typedef long long OFFSZ; int COLORMAP(int c, int *r); -#define MYREADER(p) myreader(p) -#define MYCANON(p) mycanon(p) -#define MYOPTIM - #define SHSTR (MAXSPECIAL+1) /* short struct */ #define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ #define SPCON (MAXSPECIAL+3) /* positive constant */ diff --git a/usr.bin/pcc/powerpc/order.c b/usr.bin/pcc/powerpc/order.c index 9d2ccd2d6d0..7c72c15deca 100644 --- a/usr.bin/pcc/powerpc/order.c +++ b/usr.bin/pcc/powerpc/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.3 2007/11/16 09:00:13 otto Exp $ */ +/* $OpenBSD: order.c,v 1.4 2007/12/22 14:05:04 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -93,7 +93,7 @@ myormake(NODE *q) if (x2debug) printf("myormake(%p)\n", q); -#if 1 +#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; @@ -151,18 +151,6 @@ shumul(NODE *p) } /* - * Rewrite increment/decrement operation. - */ -int -setincr(NODE *p) -{ - if (x2debug) - printf("setincr(%p)\n", p); - - return(0); -} - -/* * Rewrite operations on binary operators (like +, -, etc...). * Called as a result of table lookup. */ @@ -204,6 +192,17 @@ nspecial(struct optab *q) switch (q->op) { + case STASG: + { + static struct rspecial s[] = { + { NEVER, R3 }, + { NRIGHT, R4 }, + { NEVER, R5 }, + { 0 } }; + return s; + } + break; + case OPLTYPE: { if (q->visit & SAREG) { @@ -258,7 +257,7 @@ nspecial(struct optab *q) break; } - comperr("nspecial entry %d", q - table); + comperr("nspecial entry %d: %s", q - table, q->cstring); return 0; /* XXX gcc */ } @@ -277,8 +276,16 @@ setorder(NODE *p) int * livecall(NODE *p) { - static int r[1] = { -1 }; /* Terminate with -1 */ + static int r[] = { R3, R4, R5, R6, R7, R8, R9, R10, -1 }; return &r[0]; } +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} |