diff options
Diffstat (limited to 'usr.bin/pcc/powerpc')
-rw-r--r-- | usr.bin/pcc/powerpc/code.c | 481 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/local.c | 65 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/local2.c | 83 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/macdefs.h | 10 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/order.c | 37 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/table.c | 505 |
6 files changed, 906 insertions, 275 deletions
diff --git a/usr.bin/pcc/powerpc/code.c b/usr.bin/pcc/powerpc/code.c index 288e9d79f34..cde81183a4d 100644 --- a/usr.bin/pcc/powerpc/code.c +++ b/usr.bin/pcc/powerpc/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.1 2007/10/20 10:01:38 otto Exp $ */ +/* $OpenBSD: code.c,v 1.2 2007/11/01 10:52:58 otto Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -27,10 +27,16 @@ */ #include <assert.h> +#include <stdlib.h> -# include "pass1.h" +#include "pass1.h" #include "pass2.h" +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); + /* * cause the alignment to become a multiple of n * never called for text segment. @@ -323,12 +329,34 @@ fldty(struct symtab *p) void genswitch(int num, struct swents **p, int n) { + if (n == 0) { + if (p[0]->sval != 0) + branch(p[0]->sval); + return; + } + +#ifdef PCC_DEBUG + if (xdebug) { + int i; + for (i = 1; i <= n; i++) + printf("%d: %llu\n", i, p[i]->sval); + } +#endif + + if (0) + genswitch_table(num, p, n); + if (0) + genswitch_bintree(num, p, n); + genswitch_mrst(num, p, n); +} + +static void +genswitch_simple(int num, struct swents **p, int n) +{ NODE *r; int i; - /* simple switch code */ for (i = 1; i <= n; ++i) { - /* already in 1 */ r = tempnode(num, INT, 0, MKSUE(INT)); r = buildtree(NE, r, bcon(p[i]->sval)); cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); @@ -336,3 +364,448 @@ genswitch(int num, struct swents **p, int n) 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 +genswitch_bintree(int num, struct swents **p, int n) +{ + int lab = getlab(); + + if (p[0]->slab == 0) + p[0]->slab = lab; + + bintree_rec(num, p, n, 1, n); + + plabel(lab); +} + +static void +bintree_rec(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 = buildtree(NE, r, bcon(p[s]->sval)); + cbranch(buildtree(NOT, r, NIL), bcon(p[s]->slab)); + branch(p[0]->slab); + return; + } + + rlabel = getlab(); + + h = s + (e - s) / 2; + + r = tempnode(num, INT, 0, MKSUE(INT)); + r = buildtree(GT, r, bcon(p[h]->sval)); + cbranch(r, bcon(rlabel)); + bintree_rec(num, p, n, s, h); + plabel(rlabel); + bintree_rec(num, p, n, h+1, e); +} + + + +static void +genswitch_table(int num, struct swents **p, int n) +{ + NODE *r, *t; + int tval; + int minval, maxval, range; + int deflabel, tbllabel; + int i, j; + + minval = p[1]->sval; + maxval = p[n]->sval; + + range = maxval - minval + 1; + + if (n < 10 || range > 3 * n) { + /* too small or too sparse for jump table */ + genswitch_simple(num, p, n); + return; + } + + r = tempnode(num, UNSIGNED, 0, MKSUE(UNSIGNED)); + r = buildtree(MINUS, r, bcon(minval)); + t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED)); + tval = t->n_lval; + r = buildtree(ASSIGN, t, r); + ecomp(r); + + deflabel = p[0]->slab; + if (deflabel == 0) + deflabel = getlab(); + + t = tempnode(tval, UNSIGNED, 0, MKSUE(UNSIGNED)); + cbranch(buildtree(GT, t, bcon(maxval-minval)), bcon(deflabel)); + + tbllabel = getlab(); + struct symtab *strtbl = lookup("__switch_table", SLBLNAME|STEMP); + strtbl->soffset = tbllabel; + strtbl->sclass = ILABEL; + strtbl->stype = INCREF(UCHAR); + + t = block(NAME, NIL, NIL, UNSIGNED, 0, MKSUE(UNSIGNED)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = tempnode(tval, UNSIGNED, 0, MKSUE(INT)); + r = buildtree(PLUS, t, r); + t = tempnode(0, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = buildtree(UMUL, r, NIL); + t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = buildtree(PLUS, t, r); + r = block(GOTO, r, NIL, 0, 0, 0); + ecomp(r); + + plabel(tbllabel); + for (i = minval, j=1; i <= maxval; i++) { + char *entry = tmpalloc(20); + int lab = deflabel; + //printf("; minval=%d, maxval=%d, i=%d, j=%d p[j]=%lld\n", minval, maxval, i, j, p[j]->sval); + if (p[j]->sval == i) { + lab = p[j]->slab; + j++; + } + snprintf(entry, 20, ".long " LABFMT "-" LABFMT, lab, tbllabel); + send_passt(IP_ASM, entry); + } + + if (p[0]->slab <= 0) + plabel(deflabel); +} + +#define DPRINTF(x) if (xdebug) printf x +//#define DPRINTF(x) do { } while(0) + +#define MIN_TABLE_SIZE 8 + +/* + * Multi-way Radix Search Tree (MRST) + */ + +static void mrst_rec(int num, struct swents **p, int n, int *state, int lab); +static unsigned long mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *lowbit); +void mrst_put_entry_and_recurse(int num, struct swents **p, int n, int *state, int tbllabel, int lab, unsigned long j, unsigned long tblsize, unsigned long Wmax, int lowbit); + +static void +genswitch_mrst(int num, struct swents **p, int n) +{ + int *state; + int i; + int putlabel = 0; + + if (n < 10) { + /* too small for MRST */ + genswitch_simple(num, p, n); + return; + } + + state = tmpalloc((n+1)*sizeof(int)); + for (i = 0; i <= n; i++) + state[i] = 0; + + if (p[0]->slab == 0) { + p[0]->slab = getlab(); + putlabel = 1; + } + + mrst_rec(num, p, n, state, 0); + + if (putlabel) + plabel(p[0]->slab); +} + + +/* + * Look through the cases and generate a table or + * list of simple comparisons. If generating a table, + * invoke mrst_put_entry_and_recurse() to put + * an entry in the table and recurse. + */ +static void +mrst_rec(int num, struct swents **p, int n, int *state, int lab) +{ + int len, lowbit; + unsigned long Wmax; + unsigned int tblsize; + NODE *t; + NODE *r; + int tval; + int i; + + DPRINTF(("mrst_rec: num=%d, n=%d, lab=%d\n", num, n, lab)); + + /* find best window to cover set*/ + Wmax = mrst_find_window(p, n, state, lab, &len, &lowbit); + tblsize = (1 << len); + assert(len > 0 && tblsize > 0); + + DPRINTF(("mrst_rec: Wmax=%lu, lowbit=%d, tblsize=%u\n", + Wmax, lowbit, tblsize)); + + if (lab) + plabel(lab); + + if (tblsize <= MIN_TABLE_SIZE) { + DPRINTF(("msrt_rec: break the recursion\n")); + for (i = 1; i <= n; i++) { + if (state[i] == lab) { + t = tempnode(num, UNSIGNED, 0, MKSUE(UNSIGNED)); + cbranch(buildtree(EQ, t, bcon(p[i]->sval)), + bcon(p[i]->slab)); + } + } + branch(p[0]->slab); + return; + } + + DPRINTF(("generating table with %d elements\n", tblsize)); + + // AND with Wmax + t = tempnode(num, UNSIGNED, 0, MKSUE(UNSIGNED)); + r = buildtree(AND, t, bcon(Wmax)); + + // RS lowbits + r = buildtree(RS, r, bcon(lowbit)); + + t = tempnode(0, UNSIGNED, 0, MKSUE(UNSIGNED)); + tval = t->n_lval; + r = buildtree(ASSIGN, t, r); + ecomp(r); + + int tbllabel = getlab(); + struct symtab *strtbl = lookup("__switch_table", SLBLNAME|STEMP); + strtbl->soffset = tbllabel; + strtbl->sclass = ILABEL; + strtbl->stype = INCREF(UCHAR); + + t = block(NAME, NIL, NIL, UNSIGNED, 0, MKSUE(UNSIGNED)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = tempnode(tval, UNSIGNED, 0, MKSUE(INT)); + r = buildtree(PLUS, t, r); + t = tempnode(0, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + r = tempnode(t->n_lval, INCREF(UNSIGNED), 0, MKSUE(UNSIGNED)); + r = buildtree(UMUL, r, NIL); + t = block(NAME, NIL, NIL, UCHAR, 0, MKSUE(UCHAR)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = buildtree(PLUS, t, r); + r = block(GOTO, r, NIL, 0, 0, 0); + ecomp(r); + + plabel(tbllabel); + + mrst_put_entry_and_recurse(num, p, n, state, tbllabel, lab, + 0, tblsize, Wmax, lowbit); +} + + +/* + * Put an entry into the table and recurse to the next entry + * in the table. On the way back through the recursion, invoke + * mrst_rec() to check to see if we should generate another + * table. + */ +void +mrst_put_entry_and_recurse(int num, struct swents **p, int n, int *state, + int tbllabel, int labval, + unsigned long j, unsigned long tblsize, unsigned long Wmax, int lowbit) +{ + int i; + int found = 0; + int lab = getlab(); + + /* + * Look for labels which map to this table entry. + * Mark each one in "state" that they fall inside this table. + */ + for (i = 1; i <= n; i++) { + unsigned int val = (p[i]->sval & Wmax) >> lowbit; + if (val == j && state[i] == labval) { + found = 1; + state[i] = lab; + } + } + + /* couldn't find any labels? goto the default label */ + if (!found) + lab = p[0]->slab; + + /* generate the table entry */ + char *entry = tmpalloc(20); + snprintf(entry, 20, ".long " LABFMT "-" LABFMT, lab, tbllabel); + send_passt(IP_ASM, entry); + + DPRINTF(("mrst_put_entry: table=%d, pos=%lu/%lu, label=%d\n", + tbllabel, j, tblsize, lab)); + + /* go to the next table entry */ + if (j+1 < tblsize) { + mrst_put_entry_and_recurse(num, p, n, state, tbllabel, labval, + j+1, tblsize, Wmax, lowbit); + } + + /* if we are going to the default label, bail now */ + if (!found) + return; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("state: "); + for (i = 1; i <= n; i++) + printf("%d ", state[i]); + printf("\n"); + } +#endif + + /* build another table */ + mrst_rec(num, p, n, state, lab); +} + +/* + * counts the number of entries in a table of size (1 << L) which would + * be used given the cases and the mask (W, lowbit). + */ +static unsigned int +mrst_cardinality(struct swents **p, int n, int *state, int step, unsigned long W, int L, int lowbit) +{ + unsigned int count = 0; + int i; + + if (W == 0) + return 0; + + int *vals = (int *)calloc(1 << L, sizeof(int)); + assert(vals); + + DPRINTF(("mrst_cardinality: ")); + for (i = 1; i <= n; i++) { + int idx; + if (state[i] != step) + continue; + idx = (p[i]->sval & W) >> lowbit; + DPRINTF(("%llu->%d, ", p[i]->sval, idx)); + if (!vals[idx]) { + count++; + } + vals[idx] = 1; + } + DPRINTF((": found %d entries\n", count)); + free(vals); + + return count; +} + +/* + * Find the maximum window (table size) which would best cover + * the set of labels. Algorithm explained in: + * + * Ulfar Erlingsson, Mukkai Krishnamoorthy and T.V. Raman. + * Efficient Multiway Radix Search Trees. + * Information Processing Letters 60:3 115-120 (November 1996) + */ + +static unsigned long +mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *lowbit) +{ + unsigned int tblsize; + unsigned long W = 0; + unsigned long Wmax = 0; + unsigned long Wleft = (1 << (SZLONG-1)); + unsigned int C = 0; + unsigned int Cmax = 0; + int L = 0; + int Lmax = 0; + int lowmax = 0; + int no_b = SZLONG-1; + unsigned long b = (1 << (SZLONG-1)); + + DPRINTF(("mrst_find_window: n=%d, lab=%d\n", n, lab)); + + for (; b > 0; b >>= 1, no_b--) { + + // select the next bit + W |= b; + L += 1; + + tblsize = 1 << L; + assert(tblsize > 0); + + DPRINTF(("no_b=%d, b=0x%lx, Wleft=0x%lx, W=0x%lx, Wmax=0x%lx, L=%d, Lmax=%d, Cmax=%u, lowmax=%d, tblsize=%u\n", no_b, b, Wleft, W, Wmax, L, Lmax, Cmax, lowmax, tblsize)); + + C = mrst_cardinality(p, n, state, lab, W, L, no_b); + DPRINTF((" -> cardinality is %d\n", C)); + + if (2*C >= tblsize) { + DPRINTF(("(found good match, keep adding to table)\n")); + Wmax = W; + Lmax = L; + lowmax = no_b; + Cmax = C; + } else { + DPRINTF(("(too sparse)\n")); + assert((W & Wleft) != 0); + + /* flip the MSB and see if we get a better match */ + W ^= Wleft; + Wleft >>= 1; + L -= 1; + + DPRINTF((" --> trying W=0x%lx and L=%d and Cmax=%u\n", W, L, Cmax)); + C = mrst_cardinality(p, n, state, lab, W, L, no_b); + DPRINTF((" --> C=%u\n", C)); + if (C > Cmax) { + Wmax = W; + Lmax = L; + lowmax = no_b; + Cmax = C; + DPRINTF((" --> better!\n")); + } else { + DPRINTF((" --> no better\n")); + } + } + + } + +#ifdef PCC_DEBUG + if (xdebug) { + int i; + int hibit = lowmax + Lmax; + printf("msrt_find_window: Wmax=0x%lx, lowbit=%d, result=", Wmax, lowmax); + for (i = 31; i >= 0; i--) { + int mask = (1 << i); + if (i == hibit) + printf("["); + if (Wmax & mask) + printf("1"); + else + printf("0"); + if (i == lowmax) + printf("]"); + } + printf("\n"); + } +#endif + + assert(Lmax > 0); + *len = Lmax; + *lowbit = lowmax; + + DPRINTF(("msrt_find_window: returning Wmax=%lu, len=%d, lowbit=%d [tblsize=%u, entries=%u]\n", Wmax, Lmax, lowmax, tblsize, C)); + + return Wmax; +} diff --git a/usr.bin/pcc/powerpc/local.c b/usr.bin/pcc/powerpc/local.c index 7b921f24dc5..ad596384cf7 100644 --- a/usr.bin/pcc/powerpc/local.c +++ b/usr.bin/pcc/powerpc/local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local.c,v 1.2 2007/10/21 17:41:06 otto Exp $ */ +/* $OpenBSD: local.c,v 1.3 2007/11/01 10:52:58 otto Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -90,6 +90,10 @@ fixupfuncargs(NODE *r, int *reg) /* recurse to the bottom of the tree */ fixupfuncargs(r->n_left, reg); + if (r->n_right->n_op == STARG) { + assert(0); + } + r->n_right = block(ASSIGN, NIL, r->n_right, r->n_right->n_type, r->n_right->n_df, r->n_right->n_sue); @@ -104,6 +108,17 @@ fixupfuncargs(NODE *r, int *reg) } } else { + + if (r->n_op == STARG) { + assert(0); +#if 0 + copystructtostack(r->); + *r = *(r->n_left) + nfree(r->n_left); + return; +#endif + } + NODE *l = talloc(); *l = *r; r->n_op = ASSIGN; @@ -157,23 +172,33 @@ clocal(NODE *p) } #endif - if (kflag && p->n_left->n_op == NAME) { + 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)) { 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; l->n_rval = R31; - p->n_op = PLUS; + 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); + p->n_op = SCONV; p->n_lval = 0; - p->n_left = l; + p->n_left = r; p->n_rval = 0; - p->n_right = r; + p->n_right = 0; +#endif } } @@ -195,23 +220,21 @@ clocal(NODE *p) p = stref(block(STREF, r, p, 0, 0, 0)); break; - case STATIC: - if (q->slevel == 0) - break; - p->n_lval = 0; - p->n_sp = q; - 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 */ #if 1 default: - if (kflag && !ISFTN(p->n_type)) { - + 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; @@ -792,7 +815,7 @@ finval(NODE *p) char * exname(char *p) { -#if 0 +#ifndef ELFABI #define NCHNAM 256 static char text[NCHNAM+1]; int i; @@ -806,8 +829,11 @@ exname(char *p) text[i] = '\0'; text[NCHNAM] = '\0'; /* truncate */ + + return (text); +#else + return (p == NULL ? "" : p); #endif - return (p); } /* @@ -888,7 +914,12 @@ deflab1(int label) printf(LABFMT ":\n", label); } +#ifdef ELFABI +static char *loctbl[] = { "text", "data", "section .rodata,", + "section .rodata" }; +#else static char *loctbl[] = { "text", "data", "section .rodata,", "cstring" }; +#endif void setloc1(int locc) diff --git a/usr.bin/pcc/powerpc/local2.c b/usr.bin/pcc/powerpc/local2.c index 77d1001a248..748226f6942 100644 --- a/usr.bin/pcc/powerpc/local2.c +++ b/usr.bin/pcc/powerpc/local2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: local2.c,v 1.1 2007/10/20 10:01:38 otto Exp $ */ +/* $OpenBSD: local2.c,v 1.2 2007/11/01 10:52:58 otto Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -57,13 +57,6 @@ addstub(struct stub *list, char *name) } void -lineid(int l, char *fn) -{ - /* identify line l and file fn */ - printf("# line %d, file %s\n", l, fn); -} - -void deflab(int label) { printf(LABFMT ":\n", label); @@ -88,11 +81,11 @@ prtprolog(struct interpass_prolog *ipp, int addto) // 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]); + 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]); + 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]); + printf(" stwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]); if (kflag) { funcname = ipp->ipp_name; @@ -200,7 +193,7 @@ eoftn(struct interpass_prolog *ipp) /* return from function code */ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) { if (i & 1) - printf(" lwz %s, %d(%s)\n", + printf("\tlwz %s,%d(%s)\n", rnames[j], regoff[j], rnames[FPREG]); } @@ -215,11 +208,11 @@ eoftn(struct interpass_prolog *ipp) printf(" ret $4\n"); } else { // unwind stack frame - printf(" lwz %s,0(%s)\n", rnames[R1], rnames[R1]); - printf(" lwz %s,8(%s)\n", rnames[R0], rnames[R1]); - printf(" mtlr %s\n", rnames[R0]); - printf(" lmw %s,-8(%s)\n", rnames[R30], rnames[R1]); - printf(" blr\n"); + printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]); + 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"); } } @@ -260,7 +253,7 @@ hopcode(int f, int o) * Return type size in bytes. Used by R2REGS, arg 2 to offset(). */ int -tlen(p) NODE *p; +tlen(NODE *p) { switch(p->n_type) { case CHAR: @@ -758,24 +751,21 @@ conput(FILE *fp, NODE *p) switch (p->n_op) { case ICON: #if 0 - printf("XXX type = %x\n", p->n_type); -#endif - if (p->n_sp != NULL && -#if 0 - (p->n_sp->sclass != STATIC) && + if (p->n_sp) + printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel); #endif - (p->n_sp->sclass != ILABEL)) - s = exname(p->n_name); - else + 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)) { fprintf(fp, "%s$stub", s); addstub(&stublist, s); - } else if (kflag && p->n_sp) { -// printf("sclass=%x sflags=%x\n", p->n_sp->sclass, p->n_sp->sflags); - if (p->n_sp && (p->n_sp->sclass != STATIC && p->n_sp->sflags != SSTRING)) { + } else if (kflag) { + if (p->n_sp && p->n_sp->sclass == EXTERN) { fprintf(fp, "L%s$non_lazy_ptr", s); addstub(&nlplist, s); } else { @@ -850,15 +840,19 @@ adrput(FILE *io, NODE *p) case NAME: if (p->n_name[0] != '\0') { - if (kflag && p->n_sp && (p->n_sp->sclass == STATIC || p->n_sp->sflags != SSTRING)) { + 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) { + } 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 - fputs(exname(p->n_name), io); + } 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); + } if (p->n_lval != 0) fprintf(io, "+" CONFMT, p->n_lval); } else @@ -927,7 +921,7 @@ cbgen(int o, int lab) { if (o < EQ || o > UGT) comperr("bad conditional branch: %s", opst[o]); - printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); + printf("\t%s " LABFMT "\n", ccbranches[o-EQ], lab); } static void @@ -1150,6 +1144,19 @@ COLORMAP(int c, int *r) #endif } +#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\0%r3\0", "%r5\0%r4\0", "%r6\0%r5\0", "%r7\0%r6\0", + "%r8\0%r7\0", "%r9\0%r8\0", "%r10%r9\0", "%r15%r14", "%r17%r16", + "%r19%r18", "%r21%r20", "%r23%r22", "%r25%r24", "%r27%r26", + "%r29%r28", "%r31%r30", +}; +#else char *rnames[] = { "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", @@ -1161,6 +1168,7 @@ char *rnames[] = { "r19r18", "r21r20", "r23r22", "r25r24", "r27r26", "r29r28", "r31r30", }; +#endif /* * Return a class suitable for a specific type. @@ -1209,11 +1217,10 @@ special(NODE *p, int shape) if (o == STCALL || o == USTCALL) return SRREG; break; -#if 0 - case SSYMBOL: - if (p->n_op == NAME && !kflag) + case SPCON: + if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0xffff) == 0) return SRDIR; -#endif + break; } return SRNOPE; } diff --git a/usr.bin/pcc/powerpc/macdefs.h b/usr.bin/pcc/powerpc/macdefs.h index 3f58fb9604d..4e4406428a6 100644 --- a/usr.bin/pcc/powerpc/macdefs.h +++ b/usr.bin/pcc/powerpc/macdefs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macdefs.h,v 1.1 2007/10/20 10:01:38 otto Exp $ */ +/* $OpenBSD: macdefs.h,v 1.2 2007/11/01 10:52:58 otto Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -89,6 +89,8 @@ #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. */ @@ -97,8 +99,13 @@ typedef unsigned long long U_CONSZ; typedef long long OFFSZ; #define CONFMT "%lld" /* format for printing constants */ +#ifdef ELFABI +#define LABFMT ".L%d" /* format for printing labels */ +#else #define LABFMT "L%d" /* format for printing labels */ +#endif #define STABLBL "LL%d" /* format for stab (debugging) labels */ +#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ #define MYP2TREE(p) myp2tree(p); @@ -261,6 +268,7 @@ int COLORMAP(int c, int *r); #define SHSTR (MAXSPECIAL+1) /* short struct */ #define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ +#define SPCON (MAXSPECIAL+3) /* positive constant */ struct stub { struct { struct stub *q_forw, *q_back; } link; diff --git a/usr.bin/pcc/powerpc/order.c b/usr.bin/pcc/powerpc/order.c index 215a2a3f20c..abc6085248b 100644 --- a/usr.bin/pcc/powerpc/order.c +++ b/usr.bin/pcc/powerpc/order.c @@ -1,4 +1,4 @@ -/* $OpenBSD: order.c,v 1.1 2007/10/20 10:01:38 otto Exp $ */ +/* $OpenBSD: order.c,v 1.2 2007/11/01 10:52:58 otto Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -40,7 +40,7 @@ int canaddr(NODE *); int notoff(TWORD t, int r, CONSZ off, char *cp) { -// if (cp) return 1; + if (cp && cp[0]) return 1; return !(off < 32768 && off > -32769); /* YES */ } @@ -67,6 +67,7 @@ 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) @@ -85,15 +86,40 @@ offstar(NODE *p, int shape) void myormake(NODE *q) { -#if 0 - NODE *p; +#if 1 + NODE *p, *r; #endif if (x2debug) printf("myormake(%p)\n", q); -#if 0 +#if 1 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 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); @@ -107,6 +133,7 @@ myormake(NODE *q) tfree(p); } #endif + (void)geninsn(p, INAREG); } /* diff --git a/usr.bin/pcc/powerpc/table.c b/usr.bin/pcc/powerpc/table.c index 07d7418b344..d1696efa1ce 100644 --- a/usr.bin/pcc/powerpc/table.c +++ b/usr.bin/pcc/powerpc/table.c @@ -1,5 +1,6 @@ -/* - * $OpenBSD: table.c,v 1.2 2007/10/21 17:45:44 otto Exp $ +/*- + * $OpenBSD: table.c,v 1.3 2007/11/01 10:52:58 otto Exp $ + * * Copyright (c) 2007 Gregory McGarry <g.mcgarry@ieee.org> * * Permission to use, copy, modify, and distribute this software for any @@ -32,6 +33,16 @@ #define TSWORD TINT|TLONG #define TWORD TUWORD|TSWORD +#ifdef ELFABI +#define HA16(x) # x "@ha" +#define LO16(x) # x "@l" +#define COM " # " +#else +#define HA16(x) "ha16(" # x ")" +#define LO16(x) "lo16(" # x ")" +#define COM " ; " +#endif + struct optab table[] = { /* First entry must be an empty entry */ { -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, @@ -41,7 +52,7 @@ struct optab table[] = { SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, 0, RLEFT, - " # pointer conversion", }, + COM "pointer conversion\n", }, /* * Conversions of integral types @@ -52,28 +63,35 @@ struct optab table[] = { INAREG, TCHAR|TUCHAR, INAREG, TCHAR|TUCHAR, 0, RLEFT, - " # convert a between (u)uchar and (u)char\n", }, + COM "convert between (u)char and (u)char\n", }, + +/* convert (u)short to (u)short */ +{ SCONV, INAREG, + INAREG, TSHORT|TUSHORT, + INAREG, 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, - " # convert a pointer/word to an int\n", }, + COM "convert a pointer/word to an int\n", }, /* convert pointers to pointers */ { SCONV, INAREG, SAREG, TPOINT, SAREG, TPOINT, 0, RLEFT, - " # convert pointers\n", }, + COM "convert pointers\n", }, /* convert (u)longlong to (u)longlong */ { SCONV, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, RLEFT, - " # convert (u)longlong to (u)longlong\n", }, + COM "convert (u)longlong to (u)longlong\n", }, /* convert char to short */ @@ -81,56 +99,36 @@ struct optab table[] = { SAREG, TCHAR, SAREG, TSHORT|TSWORD, NASL|NAREG, RESC1, - " extsb A1,AL # convert char to short/int\n", }, + " extsb A1,AL" COM "convert char to short/int\n", }, /* convert uchar to short */ { SCONV, INAREG, SAREG, TUCHAR, SAREG, TSHORT|TSWORD, NASL|NAREG, RESC1, - " # convert uchar to short/int\n", }, + COM "convert uchar to short/int\n", }, -#if 0 -/* convert char to short in memory */ +/* convert uchar to ushort/uint/ulong */ { SCONV, INAREG, - SOREG, TCHAR, - SAREG, TSHORT|TSWORD, - NASL|NAREG|NSPECIAL, RESC1, - " lbz A1,AL # convert char to short/int\n" - " extsb A1,A1\n", }, -#endif - -/* convert (u)char to ushort/uint/ulong */ -{ SCONV, INAREG, - SAREG, TCHAR|TUCHAR, + SAREG, TUCHAR, SAREG, TUSHORT|TUWORD, - NASL|NAREG|NSPECIAL, RESC1, - " andi. A1,AL,255 # convert (u)char (AL) to ushort/unsigned (A1)\n", }, + 0, RLEFT, + COM "convert uchar (AL) to ushort/unsigned (A1)\n", }, -#if 0 -/* convert uchar to short/int/long in memory */ +/* XXX is this necessary? */ +/* convert char to ushort/uint/ulong */ { SCONV, INAREG, - SOREG, TUCHAR, - SAREG, TSHORT|TSWORD, + SAREG, TCHAR, + SAREG, TUSHORT|TUWORD, NASL|NAREG|NSPECIAL, RESC1, - " lbz A1,AL # convert uchar to short/int\n", }, -#endif - -#if 0 -/* convert (u)char to ushort/uint/ulong in memory */ -{ SCONV, INAREG, - SOREG, TCHAR|TUCHAR, - SAREG, TUSHORT|TUWORD|TULONG, - NASL|NAREG, RESC1, - " lbz A1,AL # convert (u)char to ushort/unsigned/ulong\n", }, -#endif + " andi. A1,AL,255" COM "convert char (AL) to ushort/unsigned (A1)\n", }, /* convert uchar/ushort/uint to (u)longlong */ { SCONV, INBREG, SAREG, TUCHAR|TUSHORT|TUNSIGNED, SBREG, TLONGLONG|TULONGLONG, NBREG, RESC1, - " mr A1,AL # convert uchar/ushort/uint to (u)longlong\n" + " mr A1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" " li U1,0\n", }, /* convert char/short/int to ulonglong */ @@ -138,7 +136,7 @@ struct optab table[] = { SAREG, TCHAR|TSHORT|TSWORD, SBREG, TULONGLONG, NBREG, RESC1, - " mr A1,AL # convert char/short/int to ulonglong\n" + " andi. A1,AL,255" COM "convert char/short/int to ulonglong\n" " li U1,0\n", }, /* convert char/short/int to longlong */ @@ -146,7 +144,7 @@ struct optab table[] = { SAREG, TCHAR|TSHORT|TSWORD, SBREG, TLONGLONG, NBREG|NBSL, RESC1, - " mr A1,AL # convert char/short/int to longlong\n" + " mr A1,AL" COM "convert char/short/int to longlong\n" " srawi U1,AL,31\n", }, /* convert (u)short to (u)char */ @@ -154,60 +152,60 @@ struct optab table[] = { SAREG, TSHORT|TUSHORT, SAREG, TCHAR|TUCHAR, NSPECIAL|NAREG|NASL, RESC1, - " andi. A1,AL,255 # convert (u)short to (u)char\n", }, - -#if 0 -/* convert (u)short to (u)char */ -{ SCONV, INAREG, - SOREG, TSHORT|TUSHORT, - SAREG, TCHAR|TUCHAR, - NSPECIAL|NAREG|NASL, RESC1, - " lbz A1,AL # convert (u)short to (u)char\n", }, -#endif + " andi. A1,AL,255" COM "convert (u)short to (u)char\n", }, +/* XXX is this really necessary? */ /* convert short to int */ { SCONV, INAREG, SAREG, TSHORT, SAREG, TWORD, NAREG|NASL|NSPECIAL, RESC1, - " andi. A1,AL,63356 # convert short to int\n", }, - -#if 0 -/* convert (u)short to uint int memory */ -{ SCONV, INAREG, - SOREG, TUSHORT|TSHORT, - SAREG, TWORD, - NAREG|NASL|NSPECIAL, RESC1, - " lha A1,AL # convert (u)short to int\n", }, -#endif + " andi. A1,AL,65535" COM "convert short to int\n", }, /* convert ushort to (u)int. */ { SCONV, INAREG, SAREG, TUSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, - " andi. A1,AL,65535 # convert ushort to word\n", }, + 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 # convert (u)int to (u)char", }, - -/* convert (u)int to (u)char */ -{ SCONV, INAREG, - SAREG, TWORD, - SANY, TCHAR|TUCHAR, - 0, RLEFT, - " # convert (u)int to (u)char\n", }, + " andi. A1,AL,255" COM "convert (u)int to (u)char", }, /* convert (u)int to (u)short */ { SCONV, INAREG, SAREG, TWORD, SAREG, TSHORT|TUSHORT, NAREG|NASL|NSPECIAL, RESC1, - " andi. A1,AL,65535 # convert (u)int to (u)short\n", }, + " andi. A1,AL,65535" COM "convert (u)int to (u)short\n", }, + +/* conversions on load from memory */ + +/* char */ +{ SCONV, INAREG, + SOREG, TCHAR, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " 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, ushort */ +{ SCONV, INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " lha A1,AL" COM "convert (u)short to int/long\n", }, /* * Subroutine calls. @@ -217,37 +215,37 @@ struct optab table[] = { SCON|SNAME, TANY, SANY, TANY, 0, 0, - " bl CL # call (args, no result) to scon/sname (CL)\n", }, + " bl CL" COM "call (args, no result) to scon/sname (CL)\n", }, { UCALL, FOREFF, SCON|SNAME, TANY, SANY, TANY, 0, 0, - " bl CL # call (no args, no result) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, no result) to scon/sname (CL)\n", }, { CALL, INAREG, SCON|SNAME, TANY, SAREG, TWORD|TPOINT|TSHORT|TUSHORT, NAREG|NASL, RESC1, /* should be 0 */ - " bl CL # call (args, result in r3) to scon/sname (CL)\n", }, + " bl CL" COM "call (args, result in r3) to scon/sname (CL)\n", }, { CALL, INBREG, SCON|SNAME, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, /* should be 0 */ - " bl CL # call (args, result in r3:r4) to scon/sname (CL)\n", }, + " bl CL" COM "call (args, result in r3:r4) to scon/sname (CL)\n", }, { UCALL, INAREG, SCON|SNAME, TANY, SAREG, TWORD|TPOINT|TSHORT|TUSHORT, NAREG|NASL, RESC1, /* should be 0 */ - " bl CL # call (no args, result in r3) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, result in r3) to scon/sname (CL)\n", }, { UCALL, INBREG, SCON|SNAME, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, /* should be 0 */ - " bl CL # call (no args, result in r3:r4) to scon/sname (CL)\n", }, + " bl CL" COM "call (no args, result in r3:r4) to scon/sname (CL)\n", }, /* struct return */ { USTCALL, FOREFF, @@ -293,22 +291,22 @@ struct optab table[] = { /* XXX AL cannot be R0 */ { PLUS, INAREG, SAREG, TWORD|TPOINT, - SONE, TANY, - NSPECIAL, RLEFT, - " addi AL,AL,AR # 1\n", }, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1, + " addi A1,AL,AR" COM "addition of constant\n", }, /* XXX AL cannot be R0 */ -{ PLUS, INAREG, +{ PLUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SSCON, TANY, - NAREG|NASL|NSPECIAL, RESC1, - " addi A1,AL,AR # addition of constant\n", }, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " addic. A1,AL,AR" COM "addition of constant\n", }, { PLUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, - " addic A1,AL,AR # 64-bit addition of constant\n" + " addic A1,AL,AR" COM "64-bit addition of constant\n" " addze U1,UL", }, { PLUS, INAREG, @@ -317,30 +315,36 @@ struct optab table[] = { NAREG|NASL|NSPECIAL, RESC1, " add A1,AL,AR\n", }, +{ PLUS, INAREG|FORCC, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " add. A1,AL,AR\n", }, + { PLUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, - " addc A1,AL,AR # 64-bit add\n" + " addc A1,AL,AR" COM "64-bit add\n" " adde U1,UL,UR\n", }, { MINUS, INAREG, SAREG, TWORD|TPOINT, - SONE, TANY, + SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, - " addi A1,AL,-1\n", }, + " addi A1,AL,-AR\n", }, -{ MINUS, INAREG, +{ MINUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SSCON, TANY, - NAREG|NASL|NSPECIAL, RESC1, - " addi A1,AL,AR\n", }, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " addi. A1,AL,-AR\n", }, { MINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, - " addic A1,AL,-AR" + " addic A1,AL,-AR\n" " addme U1,UL\n", }, { MINUS, INAREG, @@ -349,11 +353,17 @@ struct optab table[] = { NAREG|NASL|NSPECIAL, RESC1, " subf A1,AR,AL\n", }, +{ MINUS, INAREG|FORCC, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " subf. A1,AR,AL\n", }, + { MINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, - " subfc A1,AR,AL # 64-bit subtraction\n" + " subfc A1,AR,AL" COM "64-bit subtraction\n" " subfe U1,UR,UL\n", }, /* @@ -364,13 +374,25 @@ struct optab table[] = { SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, - " slw A1,AL,AR # left shift\n", }, + " slw A1,AL,AR" COM "left shift\n", }, + +{ LS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " slw. A1,AL,AR" COM "left shift\n", }, { LS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, - " slwi A1,AL,AR # left shift by constant\n", }, + " slwi A1,AL,AR" COM "left shift by constant\n", }, + +{ LS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " slwi. A1,AL,AR" COM "left shift by constant\n", }, { LS, INBREG, SBREG, TLONGLONG|TULONGLONG, @@ -382,13 +404,25 @@ struct optab table[] = { SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, - " srw A1,AL,AR # right shift\n", }, + " srw A1,AL,AR" COM "right shift\n", }, + +{ RS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srw. A1,AL,AR" COM "right shift\n", }, { RS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, - " srwi A1,AL,AR # right shift by constant\n", }, + " srwi A1,AL,AR" COM "right shift by constant\n", }, + +{ RS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srwi. A1,AL,AR" COM "right shift by constant\n", }, { RS, INBREG, SBREG, TLONGLONG|TULONGLONG, @@ -420,18 +454,18 @@ struct optab table[] = { SAREG, TANY, SCON, TANY, 0, RDEST, - " lis AL,ha16(AR)\n" - " addi AL,AL,lo16(AR)\n", }, + " lis AL," HA16(AR) "\n" + " addi AL,AL," LO16(AR) "\n", }, /* assign constant to register */ { ASSIGN, FOREFF|INBREG, SBREG, TANY, SCON, TANY, 0, RDEST, - " lis AL,ha16(AR)\n" - " addi AL,AL,lo16(AR)\n" - " lis UL,ha16(UR)\n"\ - " addi UL,UL,lo16(UR)\n", }, + " lis AL," HA16(AR) "\n" + " addi AL,AL," LO16(AR) "\n" + " lis UL," HA16(UR) "\n"\ + " addi UL,UL," LO16(UR) "\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, @@ -445,32 +479,32 @@ struct optab table[] = { SAREG, TWORD|TPOINT, SNAME, TWORD|TPOINT, NSPECIAL, RDEST, - " lis AL,ha16(AR) # assign sname to reg\n" - " lwz AL,lo16(AR)(AL)\n", }, + " 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, NSPECIAL, RDEST, - " lwz AL,AR # assign llong to reg\n" + " lwz AL,AR" COM "assign llong to reg\n" " lwz UL,UR\n" }, { ASSIGN, FOREFF|INAREG, SBREG, TLONGLONG|TULONGLONG, SNAME, TLONGLONG|TULONGLONG, NSPECIAL, RDEST, - " lis AL,ha16(AR) # assign 64-bit sname to reg\n" - " lwz AL,lo16(AR)(AL)\n" - " lis UL,ha16(UR)\n" - " lwz UL,lo16(UR)(UL)\n", }, + " lis AL," HA16(AR) COM "assign 64-bit sname to reg\n" + " lwz AL," LO16(AR) "(AL)\n" + " lis UL," HA16(UR) "\n" + " lwz UL," LO16(UR) "(UL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TSWORD, NSPECIAL, RDEST, - " lwz AL,AR # load int/pointer into llong\n" + " lwz AL,AR" COM "load int/pointer into llong\n" " srawi UL,AR,31\n" }, /* assign memory to register */ @@ -478,7 +512,7 @@ struct optab table[] = { SBREG, TLONGLONG|TULONGLONG, SOREG, TUNSIGNED|TPOINT, NSPECIAL, RDEST, - " lwz AL,AR # load uint/pointer into (u)llong\n" + " lwz AL,AR" COM "load uint/pointer into (u)llong\n" " li UL, 0\n" }, /* assign memory to register */ @@ -493,8 +527,8 @@ struct optab table[] = { SAREG, TUCHAR, SNAME, TUCHAR, NSPECIAL, RDEST, - " lis AL,ha16(AR) # assign uchar sname to reg\n" - " lbz AL,lo16(AR)(AL)\n", }, + " lis AL," HA16(AR) COM "assign uchar sname to reg\n" + " lbz AL," LO16(AR) "(AL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, @@ -509,8 +543,8 @@ struct optab table[] = { SAREG, TCHAR, SNAME, TCHAR, NSPECIAL, RDEST, - " lis AL,ha16(AR) # assign char sname to reg\n" - " lbz AL,lo16(AR)(AL)\n" + " lis AL," HA16(AR) COM "assign char sname to reg\n" + " lbz AL," LO16(AR) "(AL)\n" " extsb AL,AL\n", }, /* assign memory to register */ @@ -525,8 +559,8 @@ struct optab table[] = { SAREG, TWORD|TPOINT, SNAME, TSHORT|TUSHORT, NSPECIAL, RDEST, - " lis AL,ha16(AR)\n" - " lha AL,lo16(AR)(AL)\n", }, + " lis AL," HA16(AR) "\n" + " lha AL," LO16(AR) "(AL)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, @@ -540,15 +574,15 @@ struct optab table[] = { SNAME, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NSPECIAL, RDEST, - " lis A1,ha16(AL) # assign reg to sname\n" - " stw AR,lo16(AL)(A1)\n", }, + " 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, NSPECIAL, RDEST, - " stw AR,AL # store 64-bit value\n" + " stw AR,AL" COM "store 64-bit value\n" " stw UR,UL\n", }, /* assign register to memory */ @@ -556,10 +590,10 @@ struct optab table[] = { SNAME, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NSPECIAL, RDEST, - " lis A1,ha16(AL) # assign reg to 64-bit sname\n" - " stw AR,lo16(AL)(A1)\n" - " lis U1,ha16(UL)\n" - " stw UR,lo16(UL)(U1)\n", }, + " lis A1," HA16(AL) COM "assign reg to 64-bit sname\n" + " stw AR," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " stw UR," LO16(UL) "(U1)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, @@ -573,8 +607,8 @@ struct optab table[] = { SNAME, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, NAREG|NSPECIAL, RDEST, - " lis A1,ha16(AL)" - " stb AR,lo16(AL)(A1)\n", }, + " lis A1," HA16(AL) + " stb AR," LO16(AL) "(A1)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, @@ -588,24 +622,33 @@ struct optab table[] = { SNAME, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RDEST, - " lis A1,ha16(AL)\n" - " sth AR,lo16(AL)(A1)\n", }, + " 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, 0, RDEST, - " mr AL,AR # assign AR to AL\n", }, + " mr AL,AR" COM "assign AR to AL\n", }, { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, RDEST, - " mr AL,AR # assign UR:AR to UL:AL\n" + " 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, + 0, RDEST, + " stw AR,0(AL)" COM "indirect assign\n", }, +#endif + +#if 0 { ASSIGN, FOREFF|INAREG, SFLD, TANY, SAREG, TANY, @@ -654,7 +697,7 @@ struct optab table[] = { SAREG, TSWORD, SAREG, TSWORD, NAREG, RESC1, - " divw A1,AL,AR # signed modulo\n" + " divw A1,AL,AR" COM "signed modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, @@ -662,7 +705,7 @@ struct optab table[] = { SAREG, TWORD|TPOINT, SAREG, TUWORD|TPOINT, NAREG, RESC1, - " divwu A1,AL,AR # unsigned modulo\n" + " divwu A1,AL,AR" COM "unsigned modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, @@ -697,42 +740,42 @@ struct optab table[] = { */ { UMUL, INAREG, - SANY, TPOINT|TWORD, - SOREG, TPOINT|TWORD, + SANY, TANY, + SOREG, TWORD|TPOINT, NAREG|NSPECIAL, RESC1, - " lwz A1,AL # word load\n", }, + " lwz A1,AL" COM "word load\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TCHAR, NAREG|NSPECIAL, RESC1, - " lbz A1,AL # char load\n" + " lbz A1,AL" COM "char load\n" " extsb A1,A1\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TUCHAR, NAREG|NSPECIAL, RESC1, - " lbz A1,AL # uchar load\n", }, + " lbz A1,AL" COM "uchar load\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TSHORT, NAREG|NSPECIAL, RESC1, - " lhz A1,AL # short load\n" + " lhz A1,AL" COM "short load\n" " extsh A1,A1\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TUSHORT, NAREG|NSPECIAL, RESC1, - " lhz A1,AL # ushort load\n", }, + " lhz A1,AL" COM "ushort load\n", }, { UMUL, INBREG, SANY, TANY, SOREG, TLONGLONG|TULONGLONG, NBREG, RESC1, - " lwz A1,AL # 64-bit load\n" + " lwz A1,AL" COM "64-bit load\n" " lwz U1,UL\n", }, /* @@ -741,20 +784,34 @@ struct optab table[] = { /* compare with constant */ { OPLOG, FORCC, - SAREG, TANY, + SAREG, TSWORD|TSHORT|TCHAR, SSCON, TANY, 0, RESCC, " cmpwi AL,AR\n", }, +/* compare with constant */ +{ OPLOG, FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SSCON, TANY, + 0, RESCC, + " cmplwi AL,AR\n", }, + /* compare with register */ { OPLOG, FORCC, - SAREG, TWORD|TPOINT|TSHORT|TCHAR, - SAREG, TWORD|TPOINT|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, 0, RESCC, " cmpw AL,AR\n", }, /* compare with register */ { OPLOG, FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + 0, RESCC, + " cmplw AL,AR\n", }, + +/* compare with register */ +{ OPLOG, FORCC, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, 0, @@ -770,31 +827,35 @@ struct optab table[] = { { AND, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, - NAREG|NASL|NSPECIAL, RESC1, + NAREG|NASL|NSPECIAL, RESC1|RESCC, " and A1,AL,AR\n", }, -#if 0 +{ AND, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " and. A1,AL,AR\n", }, + /* AR must be positive */ -{ AND, INAREG, - SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, - SSCON, TANY, - 0, RLEFT, - " andi. AL,AL,AR\n", }, -#endif +{ AND, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, + SPCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " andi. A1,AL,AR\n", }, { AND, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, - " and A1,AL,AR # 64-bit and\n" + " and A1,AL,AR" COM "64-bit and\n" " and U1,UL,UR\n" }, -{ AND, INBREG, +{ AND, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, - SSCON, TANY, - 0, RLEFT, - " andi. AL,AL,AR # 64-bit and with constant\n" - " li UL,0\n" }, + SPCON, TANY, + NBREG|NBSL, RESC1|RESCC, + " andi. A1,AL,AR" COM "64-bit and with constant\n" + " li U1,0\n" }, { OR, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, @@ -802,24 +863,42 @@ struct optab table[] = { NAREG|NASL|NSPECIAL, RESC1, " or A1,AL,AR\n", }, +{ OR, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " or. A1,AL,AR\n", }, + { OR, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, - 0, RLEFT, - " ori AL,AL,AR\n", }, + NAREG|NASL|NSPECIAL, RESC1, + " ori A1,AL,AR\n", }, + +{ OR, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " ori. A1,AL,AR\n", }, { OR, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, - 0, RLEFT, - " or AL,AL,AR # 64-bit or\n" - " or UL,UL,UR\n" }, + NBREG|NBSL, RESC1, + " or A1,AL,AR" COM "64-bit or\n" + " or U1,UL,UR\n" }, { OR, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, - 0, RLEFT, - " ori AL,AL,AR # 64-bit or with constant\n" }, + NBREG|NBSL, RESC1, + " ori A1,AL,AR" COM "64-bit or with constant\n" }, + +{ OR, INBREG|FORCC, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + NBREG|NBSL, RESC1|RESCC, + " ori. A1,AL,AR" COM "64-bit or with constant\n" }, { ER, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, @@ -827,24 +906,42 @@ struct optab table[] = { NAREG|NASL|NSPECIAL, RESC1, " xor A1,AL,AR\n", }, +{ ER, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " xor. A1,AL,AR\n", }, + { ER, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, - 0, RLEFT, - " xori AL,AL,AR\n", }, + NAREG|NASL|NSPECIAL, RESC1, + " xori A1,AL,AR\n", }, + +{ ER, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " xori. A1,AL,AR\n", }, { ER, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, - " xor A1,AL,AR # 64-bit xor\n" + " xor A1,AL,AR" COM "64-bit xor\n" " xor U1,UL,UR\n" }, { ER, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, - 0, RLEFT, - " xori AL,AL,AR # 64-bit xor with constant\n" }, + NBREG|NBSL, RESC1, + " xori A1,AL,AR" COM "64-bit xor with constant\n" }, + +{ ER, INBREG|FORCC, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + NBREG|NBSL, RESC1|RESCC, + " xori. A1,AL,AR" COM "64-bit xor with constant\n" }, /* * Jumps. @@ -855,13 +952,12 @@ struct optab table[] = { 0, RNOP, " ba LL\n", }, -#ifdef GCC_COMPAT { GOTO, FOREFF, SAREG, TANY, SANY, TANY, 0, RNOP, - " ba *AL\n", }, -#endif + " mtctr AL\n" + " bctr\n", }, /* * Convert LTYPE to reg. @@ -871,93 +967,83 @@ struct optab table[] = { SANY, TANY, SOREG, TLONGLONG|TULONGLONG, NBREG, RESC1, - " lwz A1,AL # load long from memory\n" + " lwz A1,AL" COM "load long from memory\n" " lwz U1,UL\n", }, { OPLTYPE, INBREG, SANY, TANY, SNAME, TLONGLONG|TULONGLONG, NBREG, RESC1, - " lis A1,ha16(AL) # load long from sname\n" - " lwz A1,lo16(AL)(A1)\n" - " lis U1,ha16(UL)\n" - " lwz U1,lo16(UL)(U1)\n", }, + " lis A1," HA16(AL) COM "load long from sname\n" + " lwz A1," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " lwz U1," LO16(UL) "(U1)\n", }, /* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TWORD|TPOINT, NAREG, RESC1, - " lwz A1,AL # load word from memory\n", }, + " lwz A1,AL" COM "load word from memory\n", }, /* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TWORD|TPOINT, NAREG|NSPECIAL, RESC1, - " lis A1,ha16(AL) # load word from sname\n" - " lwz A1,lo16(AL)(A1)\n", }, + " 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, NAREG, RESC1, - " lbz A1,AL # load char from memory\n" - " extsb A1,A1\n", }, + " lbz A1,AL" COM "load char from memory\n" }, /* load char from memory */ { OPLTYPE, INAREG, SANY, TANY, - SNAME, TCHAR, + SNAME, TCHAR|TUCHAR, NAREG|NSPECIAL, RESC1, - " lis A1,ha16(AL) # load char from sname\n" - " lbz A1,lo16(AL)(A1)\n" - " extsb A1,A1\n", }, + " lis A1," HA16(AL) COM "load (u)char from sname\n" + " lbz A1," LO16(AL) "(A1)\n", }, /* load uchar from memory */ { OPLTYPE, INAREG, SANY, TANY, - SOREG, TUCHAR, + SOREG, TCHAR|TUCHAR, NAREG, RESC1, - " lbz A1,AL # load uchar from memory\n", }, - -/* load uchar from memory */ -{ OPLTYPE, INAREG, - SANY, TANY, - SNAME, TUCHAR, - NAREG|NSPECIAL, RESC1, - " lis A1,ha16(AL) # load uchar from sname" - " lbz A1,lo16(AL)(A1)\n", }, + " lbz A1,AL" COM "load (u)char from memory\n", }, /* load short from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TSHORT|TUSHORT, NAREG, RESC1, - " lha A1,AL # load (u)short from memory\n", }, + " lha A1,AL" COM "load (u)short from memory\n", }, /* load short from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RESC1, - " lis A1,ha16(AL) # load (u)short from sname\n" - " lha A1,lo16(AL)(A1)\n", }, + " lis A1," HA16(AL) COM "load (u)short from sname\n" + " lha A1," LO16(AL) "(A1)\n", }, /* load from 16-bit constant */ { OPLTYPE, INAREG, SANY, TANY, SSCON, TANY, NAREG, RESC1, - " li A1,AL # load 16-bit constant\n", }, + " li A1,AL" COM "load 16-bit constant\n", }, /* load from 16-bit constant */ { OPLTYPE, INBREG, SANY, TANY, SSCON, TANY, NBREG, RESC1, - " li A1,AL # load 16-bit constant\n" + " li A1,AL" COM "load 16-bit constant\n" " li U1,0\n", }, /* load from constant */ @@ -965,35 +1051,34 @@ struct optab table[] = { SANY, TANY, SCON, TANY, NAREG|NASL|NSPECIAL, RESC1, - " lis A1,ha16(AL) # load constant into register\n" - " addi A1,A1,lo16(AL)\n", }, + " 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, NBREG, RESC1, - " lis A1,ha16(AL) # load constant into register\n" - " addi A1,A1,lo16(AL)\n" - " lis U1,ha16(UL)\n" - " addi U1,U1,lo16(UL)\n", }, + " lis A1," HA16(AL) COM "load constant into register\n" + " addi A1,A1," LO16(AL) "\n" + " 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 # load AL into A1\n" }, + " mr A1,AL" COM "load AL into A1\n" }, /* load from register */ { OPLTYPE, INBREG, SANY, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG, RESC1, - " mr A1,AL # load UL:AL into U1:A1\n" + " mr A1,AL" COM "load UL:AL into U1:A1\n" " mr U1,UL\n", }, - /* * Negate a word. */ |