summaryrefslogtreecommitdiff
path: root/usr.bin/pcc
diff options
context:
space:
mode:
authorStefan Kempf <stefan@cvs.openbsd.org>2007-12-22 14:05:05 +0000
committerStefan Kempf <stefan@cvs.openbsd.org>2007-12-22 14:05:05 +0000
commit364275c5dd83730a39ae5a9a474e904ff4f2b27a (patch)
tree161b25b34d6705dd452dd2e03f1631c5fc020c04 /usr.bin/pcc
parent42fb310342bd3c17c926835e06388d425368bb54 (diff)
Sync with main repo.
Diffstat (limited to 'usr.bin/pcc')
-rw-r--r--usr.bin/pcc/powerpc/README38
-rw-r--r--usr.bin/pcc/powerpc/code.c12
-rw-r--r--usr.bin/pcc/powerpc/local.c94
-rw-r--r--usr.bin/pcc/powerpc/local2.c207
-rw-r--r--usr.bin/pcc/powerpc/macdefs.h8
-rw-r--r--usr.bin/pcc/powerpc/order.c39
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, &reg);
}
+ /* 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;
+}