diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-11-16 08:36:24 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-11-16 08:36:24 +0000 |
commit | f7d7a39b9fa388ad3592ca630db976b95437e570 (patch) | |
tree | 396b761b2dbee37ca4c53f3ce3859774263ada8f /usr.bin | |
parent | 2811f223c5884b622e45a2352c89b8654da77b35 (diff) |
sync with repo and brink in hppa backend from mickey. afaik, it needs
some changes in the mi parts that are not yet committed
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/pcc/hppa/code.c | 229 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/local.c | 759 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/local2.c | 709 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/macdefs.h | 418 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/order.c | 203 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/table.c | 1014 |
6 files changed, 3332 insertions, 0 deletions
diff --git a/usr.bin/pcc/hppa/code.c b/usr.bin/pcc/hppa/code.c new file mode 100644 index 00000000000..66300335515 --- /dev/null +++ b/usr.bin/pcc/hppa/code.c @@ -0,0 +1,229 @@ +/* $OpenBSD: code.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* + * cause the alignment to become a multiple of n + * never called for text segment. + */ +void +defalign(int n) +{ + n /= SZCHAR; + if (n == 1) + return; + printf("\t.align %d\n", n); +} + +/* + * 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); +} + + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int sz; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* address of return struct is in eax */ + /* create a call to memcpy() */ + /* will get the result in %ret0 */ + p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_rval = RET0; + q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + q->n_rval = FP; + 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); +} + +/* + * 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) +{ + int i; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* Function returns struct, adjust arg offset */ + for (i = 0; i < n; i++) + a[i]->soffset += SZPOINT(INT); +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int errors) +{ + if (errors) + return; + + printf("\t.end\n"); +} + +void +bjobcode(void) +{ + printf("\t.import $global$, data\n"); +} + +/* + * 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 \""); + 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); + } + } +} + +/* + * n integer words of zeros + */ +void +zecode(int n) +{ + printf("\t.block %d\n", n * (SZINT/SZCHAR)); +/* inoff += n * SZINT; */ +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* p points to an array of structures, each consisting + * of a constant value and a label. + * The first is >=0 if there is a default label; + * its value is the label number + * The entries p[1] to p[n] are the nontrivial cases + * XXX - fix genswitch. + */ +void +genswitch(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)); + } + if (p[0]->slab > 0) + branch(p[0]->slab); +} +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + return p; +} diff --git a/usr.bin/pcc/hppa/local.c b/usr.bin/pcc/hppa/local.c new file mode 100644 index 00000000000..f1b29522f87 --- /dev/null +++ b/usr.bin/pcc/hppa/local.c @@ -0,0 +1,759 @@ +/* $OpenBSD: local.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" +#include "pass2.h" + +/* this file contains code which is dependent on the target machine */ + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + + register struct symtab *q; + register NODE *r, *l, *s; + register int o, m, rn; + TWORD t; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + break; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + /* first four integral args are in regs */ + rn = (q->soffset >> 5) - 8; + if (rn < 4) { + r = block(REG, NIL, NIL, p->n_type, 0, 0); + r->n_lval = 0; + switch (p->n_type) { + case FLOAT: + /* TODO */ + break; + case DOUBLE: + case LDOUBLE: + /* TODO */ + break; + case LONGLONG: + case ULONGLONG: + r->n_rval = AD1 - rn / 2; + break; + default: + r->n_rval = ARG0 - rn; + } + r->n_sue = p->n_sue; + p->n_sue = NULL; + nfree(p); + p = r; + break; + } + /* FALLTHROUGH */ + + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case STATIC: + case EXTERN: + 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; + p = block(UMUL, + block(PLUS, l, r, INT, 0, 0), + NIL, p->n_type, p->n_df, MKSUE(p->n_type)); + break; + } + break; + + case ADDROF: + if (!ISFTN(p->n_left->n_type)) + break; + + t = p->n_type; + l = p->n_left; + nfree(p); + p = l; + 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; + p = block(PLUS, l, r, t, 0, 0); + break; + + case STCALL: + case CALL: + /* Fix function call arguments. On x86, just add funarg */ + 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) + /* TODO put first four into regs */ + 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) { + l = talloc(); + *l = *r; + r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type; + } + break; + + case CBRANCH: + l = p->n_left; + + /* + * Remove unneccessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + /* Type must be correct */ + t = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = t; + l->n_right->n_type = t; + } + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || l->n_type == LONGLONG || + l->n_type == ULONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKSUE(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + p = l; + break; + } + + 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 && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == UMUL || l->n_op == TEMP || + l->n_op == NAME) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case ENUMTY: + case MOETY: + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return 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) && + (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; + break; + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type)); + p->n_left->n_type = INT; + break; + + 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)); + + case LS: + case RS: + /* shift count must be in an int */ + if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32) + break; /* do not do anything */ + if (p->n_right->n_type != INT || p->n_right->n_lval > 32) + p->n_right = block(SCONV, p->n_right, NIL, + INT, 0, MKSUE(INT)); + break; + +#if 0 + case FLD: + /* already rewritten (in ASSIGN) */ + if (p->n_left->n_op == TEMP) + break; + + r = tempnode(0, p->n_type, p->n_df, p->n_sue); + l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue); + p->n_left = tcopy(r); + p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue); + break; +#endif + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(p->n_type); + if (p->n_right->n_op != FLD) + break; + break; + + case ASSIGN: + if (p->n_left->n_op != FLD) + break; + l = p->n_left; + r = tempnode(0, l->n_type, l->n_df, l->n_sue); + p = block(COMOP, + block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue), + p, p->n_type, p->n_df, p->n_sue); + s = tcopy(l->n_left); + p = block(COMOP, p, + block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue), + p->n_type, p->n_df, p->n_sue); + l->n_left = tcopy(r); + break; + } +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +void +myp2tree(NODE *p) +{ +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * 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. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * 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. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ + + /* 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(PLUSEQ, 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! */ + +} + +#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"); + } +} +#endif + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. Location is already set. + */ +void +instring(char *str) +{ + char *s; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 64) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf("\t.zero %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +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; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + * + * XXX this relies on the host fp numbers representation + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; + TWORD t; + int i; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + 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); + break; + case INT: + case UNSIGNED: + printf("\t.long 0x%x", (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)); + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + 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; + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONG: + MODTYPE(type,INT); + break; + + case ULONG: + MODTYPE(type,UNSIGNED); + } + + return (type); +} + +void +calldec(NODE *p, NODE *q) +{ + printf("\t.call\n"); +} + +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 +} + +/* 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("\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); +} + +/* 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,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); +} + +/* + * print a (non-prog) label. + */ +void +deflab1(int label) +{ + printf("\t.label\t" LABFMT "\n", label); +} + +static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" }; + +void +setloc1(int locc) +{ + 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 new file mode 100644 index 00000000000..c3800e493f6 --- /dev/null +++ b/usr.bin/pcc/hppa/local2.c @@ -0,0 +1,709 @@ +/* $OpenBSD: local2.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include <ctype.h> +# include <string.h> + +void acon(NODE *p); +int argsize(NODE *p); + +static int stkpos; + +static const int rl[] = + { R1, R5, R7, R9, R11, R13, R15, R17, T4, T2, ARG3, ARG1, RET1 }; +static const int rh[] = + { R31, R4, R6, R8, R10, R12, R14, R16, T3, T1, ARG2, ARG0, RET0 }; + +void +deflab(int label) +{ + printf("\t.label\t" LABFMT "\n", label); +} + +static int regoff[MAXREGS]; +static TWORD ftype; + +/* + * Print out the prolog assembler. + * addto and regoff are already calculated. + */ +static void +prtprolog(struct interpass_prolog *ipp, int addto) +{ + int i; + + printf("\tcopy\t%%r3,%%r1\n" + "\tcopy\t%%sp,%%r3\n" + "\tstw,ma\t%%r1,%d(%%sp)\n", addto); + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + if (i <= R31) + printf("\tstw\t%s,%d(%s)\n", + rnames[i], regoff[i], rnames[FPREG]); + else if (i < RETD0) + printf("\tstw\t%s,%d(%s)\n\tstw\t%s,%d(%s)\n", + rnames[rl[i - RD0]], regoff[i] + 0, rnames[FPREG], + rnames[rh[i - RD0]], regoff[i] + 4, rnames[FPREG]); + else if (i <= FR31) + ; + else + ; + } +} + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int i, addto; + + addto = 32; + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + regoff[i] = addto; + addto += SZINT/SZCHAR; + } + addto += p2maxautooff; + return (addto + 63) & ~63; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + + ftype = ipp->ipp_type; + printf("\t.align\t4\n"); + if (ipp->ipp_vis) + printf("\t.export\t%s, code\n", ipp->ipp_name); + printf("\t.label\t%s\n\t.proc\n", ipp->ipp_name); + + /* + * We here know what register to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); + printf("\t.callinfo frame=%d, save_rp, save_sp\n\t.entry\n", addto); + prtprolog(ipp, addto); +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + printf("\tldw\t%d(%s),%s\n", + regoff[i], rnames[FPREG], rnames[i]); + + /* TODO restore sp,rp */ + printf("\tbv\t%%r0(%%rp)\n\tnop\n" + "\t.exit\n\t.procend\n\t.size\t%s, .-%s\n", + ipp->ipp_name, ipp->ipp_name); +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + 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; + case EQ: + str = "="; + break; + case NE: + str = "<>"; + break; + case LE: + str = "<"; + break; + case LT: + str = "<="; + break; + case GE: + str = ">"; + break; + case GT: + str = ">="; + break; + case ULE: + str = "<<"; + break; + case ULT: + str = "<<="; + break; + case UGE: + str = ">>"; + break; + case UGT: + str = ">>="; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case FLOAT: + return(SZFLOAT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + 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 0; +} + +void +zzzcode(NODE *p, int c) +{ + int n; + + switch (c) { + + case 'C': /* after-call fixup */ + n = p->n_qual; + if (n) + printf("\tldo\t-%d(%%sp),%%sp\n", n); + break; + + case 'P': /* returning struct-call setup */ + n = p->n_qual; + if (n) + printf("\tldo\t%d(%%sp),%%sp\n", n); + break; + + case 'F': /* output extr/dep offset/len parts for bitfields */ + + default: + comperr("zzzcode %c", c); + } +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o == NAME || o == REG || o == ICON || o == OREG || + (o == UMUL && shumul(p->n_left))) + return(1); + return(0); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (isreg(p)) + return SRDIR; /* Direct match */ + + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + /* fix for L% and R% */ + printf(CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "RR'%s", p->n_name); + if (val) + fprintf(fp, "+%d", val); + fprintf(fp, "-$global$"); + } else + fprintf(fp, "%d", val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + size /= SZCHAR; + switch (p->n_op) { + case REG: + printf("%s", rnames[rh[p->n_rval - RD0]]); + break; + + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + + case ICON: + case NAME: + if (p->n_name[0] != '\0') { + printf("LL'%s", p->n_name); + if (p->n_lval != 0) + printf("+" CONFMT, p->n_lval); + printf("-$global$"); + } else + printf("L%%" CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case ICON: + case NAME: + if (p->n_name[0] != '\0') { + fprintf(io, "RR'%s", p->n_name); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + fprintf(io, "-$global$"); + } else + fprintf(io, "R%%" CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (p->n_name[0] != '\0') { + fprintf(io, "RR'%s", p->n_name); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + fprintf(io, "-$global$"); + } else if (p->n_lval) + fprintf(io, "%d", (int)p->n_lval); + if (R2TEST(r)) { + fprintf(io, "%s(%s)", rnames[R2UPK1(r)], + rnames[R2UPK2(r)]); + } 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]]); + else + fprintf(io, "%s", rnames[p->n_rval]); + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* not used */ +void +cbgen(int o, int lab) +{ +} + +static void +fixcalls(NODE *p) +{ + /* Prepare for struct return by allocating bounce space on stack */ + switch (p->n_op) { + case STCALL: + case USTCALL: + if (p->n_stsize+p2autooff > stkpos) + stkpos = p->n_stsize+p2autooff; + break; + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + stkpos = p2autooff; + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, fixcalls); + } + if (stkpos > p2autooff) + p2autooff = stkpos; + if (stkpos > p2maxautooff) + p2maxautooff = stkpos; + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2); +} + +void +myoptim(struct interpass *ip) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + int sl, sh, dl, dh; + + switch (t) { + case LONGLONG: + case ULONGLONG: + sl = rl[s-RD0]; + sh = rh[s-RD0]; + dl = rl[d-RD0]; + dh = rh[d-RD0]; + + /* 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 (sl != dl) + printf("\tcopy\t%s,%s\n", rnames[sl], rnames[dl]); + if (sh != dh) + printf("\tcopy\t%s,%s\n", rnames[sh], rnames[dh]); + break; + case FLOAT: + printf("\tfcpy,sgl\t%s,%s\n", rnames[s], rnames[d]); + break; + case DOUBLE: + case LDOUBLE: + printf("\tfcpy,dbl\t%s,%s\n", rnames[s], rnames[d]); + break; + default: + printf("\tcopy\t%s,%s\n", rnames[s], rnames[d]); + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + num = 2 * r[CLASSB]; + num += r[CLASSA]; + return num < 28; + case CLASSB: + num = r[CLASSA]; + num += r[CLASSB] * 2; + return num < 28; + case CLASSC: + num = (r[CLASSD] > 8? 8 : r[CLASSD]) * 2; + num += r[CLASSC]; + return num < 28; + case CLASSD: + num = (r[CLASSC] + 1) / 2; + num += r[CLASSD]; + return num < 28; + } + return 0; /* XXX gcc */ +} + +const char * const rnames[MAXREGS] = { + "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9", + "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18", + "%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp", + "%ret0", "%ret1", "%sp", "%r31", + "%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7", + "%td2", "%td1", "%ad1", "%ad0", "%retd0", + "%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10", + "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18", + "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26", + "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", + "%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r", + "%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r", + "%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r", + "%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r", + "%fr16l", "%fr16r", "%fr17l", "%fr17r", +#ifdef __hppa64__ + "%fr18l", "%fr18r", "%fr19l", "%fr19r", + "%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r", + "%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r", + "%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r", + "%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r", +#endif +}; + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + switch (t) { + case LONGLONG: + case ULONGLONG: + return CLASSB; + case FLOAT: + return CLASSC; + case DOUBLE: + case LDOUBLE: + return CLASSD; + default: + return CLASSA; + } +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 64; + + p->n_qual = size; + 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); + op->n_qual = size; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + + switch (shape) { + case SFUNCALL: + if (o == STCALL || o == USTCALL) + return SRREG; + break; + case SPICON: + if (o != ICON || p->n_name[0] || + p->n_lval < -1024 || p->n_lval >= 1024) + break; + return SRDIR; + case SPCON: + if (o != ICON || p->n_name[0] || + p->n_lval < -8192 || p->n_lval >= 8192) + break; + return SRDIR; + case SPNAME: + if (o != ICON || !p->n_name[0]) + break; + return SRDIR; + } + return SRNOPE; +} diff --git a/usr.bin/pcc/hppa/macdefs.h b/usr.bin/pcc/hppa/macdefs.h new file mode 100644 index 00000000000..b2addf2fef2 --- /dev/null +++ b/usr.bin/pcc/hppa/macdefs.h @@ -0,0 +1,418 @@ +/* $OpenBSD: macdefs.h,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) (lastcon = (lastcon<<8)|((val<<24)>>24)) + +#define ARGINIT (32*8) /* bits below fp where args start */ +#define AUTOINIT (4*8) /* bits above fp where locals start */ + +/* + * storage sizes + */ +#define SZCHAR 8 +#define SZBOOL 8 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 /* or later 128 */ +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * alignment requirements + */ +#define ALCHAR 8 +#define ALBOOL 8 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 64 +#define ALLDOUBLE 64 /* 128 later */ +#define ALLONG 32 +#define ALLONGLONG 64 +#define ALSHORT 16 +#define ALPOINT 32 +#define ALSTRUCT 64 +#define ALSTACK 64 + +/* + * type value limits + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fffffff-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 (-0x7fffffffffffffffLL-1) +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR +#define WCHAR_TYPE INT +#define ENUMSIZE(high,low) INT + +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +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 */ + +#undef BACKAUTO /* stack grows upwards */ +#undef BACKTEMP /* stack grows upwards */ + +#define MYP2TREE(p) myp2tree(p) + +#define FIELDOPS /* have bit field ops */ +#define LTORBYTES /* big endian */ + +#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 ? 2 : 1) + +#define R1 0 +#define RP 1 +#define FP 2 +#define R4 3 +#define R5 4 +#define R6 5 +#define R7 6 +#define R8 7 +#define R9 8 +#define R10 9 +#define R11 10 +#define R12 11 +#define R13 12 +#define R14 13 +#define R15 14 +#define R16 15 +#define R17 16 +#define R18 17 +#define T4 18 +#define T3 19 +#define T2 20 +#define T1 21 +#define ARG3 22 +#define ARG2 23 +#define ARG1 24 +#define ARG0 25 +#define DP 26 +#define RET0 27 +#define RET1 28 +#define SP 29 +#define R31 30 + +/* double regs overlay */ +#define RD0 31 /* r1:r31 */ +#define RD1 32 /* r5:r4 */ +#define RD2 33 /* r7:r6 */ +#define RD3 34 /* r9:r8 */ +#define RD4 35 /* r11:r10 */ +#define RD5 36 /* r13:r12 */ +#define RD6 37 /* r15:r14 */ +#define RD7 38 /* r17:r16 */ +#define TD2 39 /* t4:t3 */ +#define TD1 40 /* t2:t1 */ +#define AD2 41 /* arg3:arg2 */ +#define AD1 42 /* arg1:arg0 */ +#define RETD0 43 /* ret1:ret0 */ + +/* FPU regs */ +#define FR0 44 +#define FR4 45 +#define FR5 46 +#define FR6 47 +#define FR7 48 +#define FR8 49 +#define FR9 50 +#define FR10 51 +#define FR11 52 +#define FR12 53 +#define FR13 54 +#define FR14 55 +#define FR15 56 +#define FR16 57 +#define FR17 58 +#define FR18 59 +#define FR19 60 +#define FR20 61 +#define FR21 62 +#define FR22 63 +#define FR23 64 +#define FR24 65 +#define FR25 66 +#define FR26 67 +#define FR27 68 +#define FR28 69 +#define FR29 70 +#define FR30 71 +#define FR31 72 + +#define FR0L 73 +#define FR0R 74 +#define FR4L 75 +#define FR4R 76 +#define FR5L 77 +#define FR5R 78 +#define FR6L 79 +#define FR6R 80 +#define FR7L 81 +#define FR7R 82 +#define FR8L 83 +#define FR8R 84 +#define FR9L 85 +#define FR9R 86 +#define FR10L 87 +#define FR10R 88 +#define FR11L 89 +#define FR11R 90 +#define FR12L 91 +#define FR12R 92 +#define FR13L 93 +#define FR13R 94 +#define FR14L 95 +#define FR14R 96 +#define FR15L 97 +#define FR15R 98 +#define FR16L 99 +#define FR16R 100 +#define FR17L 101 +#define FR17R 102 +#ifdef __hppa64__ +#define FR18L 103 +#define FR18R 104 +#define FR19L 105 +#define FR19R 106 +#define FR20L 107 +#define FR20R 108 +#define FR21L 109 +#define FR21R 110 +#define FR22L 111 +#define FR22R 112 +#define FR23L 113 +#define FR23R 114 +#define FR24L 115 +#define FR24R 116 +#define FR25L 117 +#define FR25R 118 +#define FR26L 119 +#define FR26R 120 +#define FR27L 121 +#define FR27R 122 +#define FR28L 123 +#define FR28R 124 +#define FR29L 125 +#define FR29R 126 +#define FR30L 127 +#define FR30R 128 +#define FR31L 129 +#define FR31R 130 + +#define MAXREGS 131 +#else +#define MAXREGS 103 +#endif + +#define RSTATUS \ + SAREG|TEMPREG, 0, 0, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + 0, SAREG|TEMPREG, SAREG|TEMPREG, 0, SAREG|TEMPREG, \ + /* double overlays */ \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + /* double-precision floats */ \ + 0, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, \ + /* single-precision floats */ \ + 0, 0, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, +#ifdef __hppa64__ + SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, +#endif + +#define ROVERLAP \ + { RD0, -1 }, { -1 }, { -1 }, \ + { RD1, -1 }, { RD1, -1 }, \ + { RD2, -1 }, { RD2, -1 }, \ + { RD3, -1 }, { RD3, -1 }, \ + { RD4, -1 }, { RD4, -1 }, \ + { RD5, -1 }, { RD5, -1 }, \ + { RD6, -1 }, { RD6, -1 }, \ + { RD7, -1 }, { RD7, -1 }, \ + { -1 }, \ + { TD2, -1 }, { TD2, -1 }, \ + { TD1, -1 }, { TD1, -1 }, \ + { AD2, -1 }, { AD2, -1 }, \ + { AD1, -1 }, { AD1, -1 }, \ + { -1 }, \ + { RETD0, -1 }, { RETD0, -1 }, \ + { -1 }, { RD0, -1 }, \ + { R1, R31, -1 }, \ + { R4, R5, -1 }, \ + { R6, R7, -1 }, \ + { R8, R9, -1 }, \ + { R10, R11, -1 }, \ + { R12, R13, -1 }, \ + { R14, R15, -1 }, \ + { R16, R17, -1 }, \ + { T4, T3, -1 }, \ + { T2, T1, -1 }, \ + { ARG3, ARG2, -1 }, \ + { ARG1, ARG0, -1 }, \ + { RET1, RET0, -1 }, \ + { -1 }, \ + { FR4L, FR4R, -1 }, \ + { FR5L, FR5R, -1 }, \ + { FR6L, FR6R, -1 }, \ + { FR7L, FR7R, -1 }, \ + { FR8L, FR8R, -1 }, \ + { FR9L, FR9R, -1 }, \ + { FR10L, FR10R, -1 }, \ + { FR11L, FR11R, -1 }, \ + { FR12L, FR12R, -1 }, \ + { FR13L, FR13R, -1 }, \ + { FR14L, FR14R, -1 }, \ + { FR15L, FR15R, -1 }, \ + { FR16L, FR16R, -1 }, \ + { FR17L, FR17R, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, { -1 }, \ + { FR4, -1 }, { FR4, -1 }, \ + { FR5, -1 }, { FR5, -1 }, \ + { FR6, -1 }, { FR6, -1 }, \ + { FR7, -1 }, { FR7, -1 }, \ + { FR8, -1 }, { FR8, -1 }, \ + { FR9, -1 }, { FR9, -1 }, \ + { FR10, -1 }, { FR10, -1 }, \ + { FR11, -1 }, { FR11, -1 }, \ + { FR12, -1 }, { FR12, -1 }, \ + { FR13, -1 }, { FR13, -1 }, \ + { FR14, -1 }, { FR14, -1 }, \ + { FR15, -1 }, { FR15, -1 }, \ + { FR16, -1 }, { FR16, -1 }, \ + { FR17, -1 }, { FR17, -1 }, +#ifdef __hppa64__ + { FR18, -1 }, { FR18, -1 }, \ + { FR19, -1 }, { FR19, -1 }, \ + { FR20, -1 }, { FR20, -1 }, \ + { FR21, -1 }, { FR21, -1 }, \ + { FR22, -1 }, { FR22, -1 }, \ + { FR23, -1 }, { FR23, -1 }, \ + { FR24, -1 }, { FR24, -1 }, \ + { FR25, -1 }, { FR25, -1 }, \ + { FR26, -1 }, { FR26, -1 }, \ + { FR27, -1 }, { FR27, -1 }, \ + { FR28, -1 }, { FR28, -1 }, \ + { FR29, -1 }, { FR29, -1 }, \ + { FR30, -1 }, { FR30, -1 }, \ + { FR31, -1 }, { FR31, -1 }, +#endif + +#define PCLASS(p) \ + (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \ + (p->n_type == FLOAT ? SCREG : \ + (p->n_type == DOUBLE || p->n_type == LDOUBLE ? SDREG : SAREG))) + +#define NUMCLASS 4 /* highest number of reg classes used */ + +int COLORMAP(int c, int *r); +TOWRD gtype(int); +#define PERMTYPE(x) ((x) < 31? INT : ((x) < 44? LONGLONG : ((x) < 73? LDOUBLE : FLOAT))) +#define GCLASS(x) ((x) < 31? CLASSA : ((x) < 44? CLASSB : ((x) < 73? CLASSD : CLASSC))) +#define DECRA(x,y) (((x) >> (y*8)) & 255) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 8) /* A1 */ +#define ENCRA2(x) ((x) << 16) /* A2 */ +#define ENCRA(x,y) ((x) << (8+y*8)) /* encode regs in int */ +#define RETREG(x) (x == LONGLONG || x == ULONGLONG ? RETD0 : \ + x == FLOAT? FR4L : \ + x == DOUBLE || x == LDOUBLE ? FR4 : RET0) + +#define FPREG FP /* frame pointer */ +#define STKREG SP /* stack pointer */ + +#define MYREADER(p) myreader(p) +#define MYCANON(p) mycanon(p) +#define MYOPTIM + +#define SFUNCALL (MAXSPECIAL+1) /* struct assign after function call */ +#define SPCON (MAXSPECIAL+2) /* smaller constant */ +#define SPICON (MAXSPECIAL+3) /* even smaller constant */ +#define SPNAME (MAXSPECIAL+4) /* ext symbol reference load/store */ diff --git a/usr.bin/pcc/hppa/order.c b/usr.bin/pcc/hppa/order.c new file mode 100644 index 00000000000..c1ba92c913d --- /dev/null +++ b/usr.bin/pcc/hppa/order.c @@ -0,0 +1,203 @@ +/* $OpenBSD: order.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include <string.h> + +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 */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if (p->n_op == PLUS || p->n_op == MINUS) { + if (r->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +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, 0); + tfree(p); + } +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on hppa */ + return SOREG; +} + +/* + * 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. + */ +int +setbin(NODE *p) +{ + if (x2debug) + printf("setbin(%p)\n", p); + + return 0; +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p,%s)\n", p, prcook(cookie)); + + if (p->n_left->n_op == FLD && !isreg(p->n_left->n_left)) { + NODE *l, *r; + int reg; + + geninsn(p->n_left->n_left, INAREG); + + reg = DECRA(p->n_left->n_left->n_reg, 0); + l = tcopy(p->n_left->n_left); + p->n_left->n_left->n_op = REG; + p->n_left->n_left->n_rval = reg; + p->n_left->n_left->n_lval = 0; + r = tcopy(p->n_left->n_left); + + geninsn(p->n_left, INAREG); + l = mkbinode(ASSIGN, l, r, l->n_type); + geninsn(l, INAREG); + return (1); + } + + return (0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + if (x2debug) + printf("setuni(%p,%s)\n", p, prcook(cookie)); + + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +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. + */ +int * +livecall(NODE *p) +{ + static int r[1] = { -1 }; /* Terminate with -1 */ + + return &r[0]; +} + diff --git a/usr.bin/pcc/hppa/table.c b/usr.bin/pcc/hppa/table.c new file mode 100644 index 00000000000..965d8e56219 --- /dev/null +++ b/usr.bin/pcc/hppa/table.c @@ -0,0 +1,1014 @@ +/* $OpenBSD: table.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pass2.h" + +#define TLL TLONGLONG|TULONGLONG +#define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +#define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +#define ANYFIXED ANYSIGNED|ANYUSIGNED +#define TUWORD TUNSIGNED|TULONG +#define TSWORD TINT|TLONG +#define TWORD TUWORD|TSWORD +#define THWORD TUSHORT|TSHORT +#define TBYTE TUCHAR|TCHAR + +#define SHINT SAREG /* char, short and int */ +#define ININT INAREG +#define SHLL SBREG /* shape for long long */ +#define INLL INBREG +#define SHFL SCREG /* shape for float */ +#define INFL INCREG +#define SHDBL SDREG /* shape for double */ +#define INDBL INDREG + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + "", }, +/* + * A bunch conversions of integral<->integral types + * There are lots of them, first in table conversions to itself + * and then conversions from each type to the others. + */ + +/* itself to itself, including pointers */ + +/* convert int,short,char <-> int,short,char. */ +{ SCONV, ININT, + SHINT, TBYTE, + SHINT, TBYTE, + 0, RLEFT, + "", }, + +{ SCONV, ININT, + SHINT, THWORD, + SHINT, THWORD, + 0, RLEFT, + "", }, + +{ SCONV, ININT, + SHINT, TWORD, + SHINT, TWORD, + 0, RLEFT, + "", }, + +/* convert pointers to int. */ +{ SCONV, ININT, + SHINT, TPOINT|TWORD, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert (u)longlong to (u)longlong. */ +{ SCONV, INLL, + SHLL, TLL, + SHLL, TLL, + 0, RLEFT, + "", }, + +/* convert pointers to pointers. */ +{ SCONV, ININT, + SHINT, TPOINT, + SANY, TPOINT, + 0, RLEFT, + "", }, + +/* convert double <-> ldouble. nothing to do here (or support quads later) */ +{ SCONV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RLEFT, + "", }, + +/* convert float -> double */ +{ SCONV, INFL, + SHFL, TFLOAT, + SHDBL, TDOUBLE|TLDOUBLE, + 0, 0, + "\tfcnvff,sgl,dbl AL,AR\n", }, + +/* convert double -> float */ +{ SCONV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHFL, TFLOAT, + 0, 0, + "\tfcnvff,dbl,sgl\tAL,AR\n", }, + +/* convert int,short,char to (u)long long */ +{ SCONV, INLL, + SHINT, ANYSIGNED, + SANY, TLL, + NBREG, RESC1, + "\tcopy\tAL,A1\n" + "\textrs\tAL,0,1,U1\n", }, + +/* convert unsigned int,short,char to (u)long long */ +{ SCONV, INLL, + SHINT, TWORD, + SANY, TLL, + NBREG, RESC1, + "\tcopy\tAL,A1\n" + "\tcopy\t%r0,U1\n", }, + +/* convert int,short,char (in memory) to float */ +{ SCONV, INFL, + SOREG, ANYSIGNED, + SHFL, TFLOAT, + NCREG, RESC1, + "\tfldws\tAL,A1\n" + "\tfcnvxf,sgl,sgl\tA1,A1\n", }, + +/* convert int,short,char (in memory) to double */ +{ SCONV, INDBL, + SOREG, TSWORD, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldws\tAL,A1\n" + "\tfcnvxf,sgl,dbl\tA1,A1\n", }, + +/* convert (u)long (in memory) to double */ +{ SCONV, INDBL, + SOREG, TLL, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldds\tAL,A1\n" + "\tfcnvxf,dbl,dbl\tA1,A1\n", }, + +/* convert int,short,char (in register) to float */ +{ SCONV, INFL, + SHINT, TSWORD, + SHFL, TFLOAT, + NCREG, RESC1, + "\tstw,ma\tAL,4(%sp)\n" + "\tfldws,ma\t-4(%sp),A1\n" + "\tfcnvxf,sgl,sgl\tA1,A1\n", }, + +/* convert int,short,char (in register) to double */ +{ SCONV, INDBL, + SHINT, TSWORD, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tstw,ma\tAL,4(%sp)\n" + "\tfldws,mb\t-4(%sp),AR\n" + "\tfcnvxf,sgl,dbl\tA1,A1\n", }, + +/* convert (u)long (in register) to double */ +{ SCONV, INDBL, + SHLL, TLL, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tldo\t8(%sp),%sp\n" + "\tstw\tAL,-8(%sp)\n" + "\tstw\tUL,-4(%sp)\n" + "\tfldds,mb\t-8(%sp),A1\n" + "\tfcnvxf,dbl,dbl\tA1,A1\n", }, + +/* convert char to (unsigned) short/int. */ +{ SCONV, ININT, + SAREG, TCHAR, + SAREG, THWORD|TWORD, + NASL|NAREG, RESC1, + "\textrs\tAL,31,8,A1\n", }, + +/* convert unsigned char to (unsigned) short/int. */ +{ SCONV, ININT, + SAREG, TUCHAR, + SAREG, THWORD|TWORD, + NASL|NAREG, RESC1, + "\textru\tAL,31,8,A1\n", }, + +/* convert char to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TCHAR, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textrs\tAL,31,8,A1\n\textrs\tA1,0,1,U1", }, + +/* convert unsigned char to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TUCHAR, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textru\tAL,31,8,A1\n\tcopy\t%r0,U1", }, + +/* convert short to (unsigned) int. */ +{ SCONV, ININT, + SAREG, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + "\textrs\tAL,31,16,A1\n", }, + +/* convert unsigned short to (unsigned) int. */ +{ SCONV, ININT, + SAREG, TUSHORT, + SAREG, THWORD, + NASL|NAREG, RESC1, + "\textru\tAL,31,16,A1\n", }, + +/* convert short to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TSHORT, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textrs\tAL,31,16,A1\n\textrs\tA1,0,1,U1", }, + +/* convert unsigned short to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TUSHORT, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textru\tAL,31,16,A1\n\tcopy\t%r0,U1", }, + +/* convert int,short,char (in memory) to int,short,char */ +{ SCONV, ININT, + SOREG, TBYTE, + SHINT, TBYTE|TPOINT, + NAREG|NASL, RESC1, + "\tldb\tAL,A1\n", }, + +{ SCONV, ININT, + SOREG, THWORD, + SHINT, THWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldh\tAL,A1\n", }, + +{ SCONV, ININT, + SOREG, TWORD, + SHINT, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +/* convert (u)long long (in register) to int,short,char */ +{ SCONV, ININT, + SHLL, TLL, + SHINT, ANYFIXED, + NAREG|NASL, RESC1, + "\tcopy\tAL,A1\n", }, + +/* convert (u)long (in memory) to int,short,char */ +{ SCONV, ININT, + SOREG, TLL, + SHINT, ANYFIXED, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +/* convert float (in register) to (u)int */ +{ SCONV, ININT, + SHFL, TFLOAT, + SHINT, TWORD, + NAREG, RESC1, + "\tfcnvfxt,sgl,sgl\tAL,AL\n" + "\tfstws,ma\tAL,4(%sp)\n" + "\tldw,mb\t-1(%sp),A1\n", }, + +/* convert double (in register) to (u)int */ +{ SCONV, ININT, + SHDBL, TDOUBLE|TLDOUBLE, + SHINT, TWORD, + NCREG|NCSL|NAREG, RESC2, + "\tfcnvfxt,dbl,sgl\tAL,A1\n" + "\tfstws,ma\tA1,4(%sp)\n" + "\tldw,mb\t-1(%sp),A2\n", }, + +/* convert float (in register) to (u)long */ +{ SCONV, INLL, + SHFL, TFLOAT, + SHLL, TLL, + NDREG|NDSL|NBREG, RESC2, + "\tfcnvfxt,sgl,dbl\tAL,A1\n" + "\tfstds,ma\tA1,8(%sp)\n" + "\tldw\t-8(%sp),A2\n" + "\tldw\t-4(%sp),U2\n" + "\tldo\t-8(%sp),%sp)\n", }, + +/* convert double (in register) to (u)long */ +{ SCONV, INLL, + SHDBL, TDOUBLE|TLDOUBLE, + SHLL, TLL, + NBREG, RESC1, + "\tfcnvfxt,dbl,dbl\tAL,AL\n" + "\tfstds,ma\tAL,8(%sp)\n" + "\tldw\t-8(%sp),A1\n" + "\tldw\t-4(%sp),U1\n" + "\tldo\t-8(%sp),%sp)\n", }, + +/* + * Subroutine calls. + */ + +{ CALL, ININT, + SAREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, ININT, + SOREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tble\tAL\n" + "\tcopy\t%r1,rp\nZC", }, + +{ CALL, INLL, + SAREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INLL, + SAREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, INFL, + SAREG, TANY, + SHFL, TFLOAT, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INFL, + SAREG, TANY, + SHFL, TFLOAT, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, INDBL, + SAREG, TANY, + SHDBL, TDOUBLE|TLDOUBLE, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INFL, + SAREG, TANY, + SHDBL, TDOUBLE|TLDOUBLE, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +/* + * The next rules handle all binop-style operators. + */ +/* TODO fix char/short overflows */ + +{ PLUS, INLL, + SHLL, TLL, + SPICON, TANY, + NBREG|NBSL, RESC1, + "\taddi\tAL,AR,A1\n" + "\taddc\tUL,%r0,U1\n", }, + +{ PLUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tadd\tAL,AR,A1\n" + "\taddc\tUL,UR,U1\n", }, + +{ PLUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfadd,sgl\tAL,AR,A1\n", }, + +{ PLUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfadd,dbl\tAL,AR,A1\n", }, + +{ PLUS, ININT, + SHINT, ANYFIXED|TPOINT, + SONE, TANY, + NAREG|NASL, RESC1, + "\tldo\t1(AL),A1\n", }, + +{ PLUS, ININT, + SHINT, ANYFIXED|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + "\tldo\tCR(AL),A1\n", }, + +{ MINUS, INLL, + SHLL, TLL, + SPICON, TANY, + NBREG|NBSL|NBSR, RESC1, + "\tsubi\tAL,AR,A1\n" + "\tsubb\tUL,%r0,U1\n", }, + +{ PLUS, ININT, + SHINT, TANY|TPOINT, + SPNAME, TANY, + NAREG|NASL, RESC1, + "\tldo\tAR(AL),A1\n", }, + +{ MINUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tsub\tAL,AR,A1\n" + "\tsubb\tUL,UR,U1\n", }, + +{ MINUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfsub,sgl\tAL,AR,A1\n", }, + +{ MINUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfsub,dbl\tAL,AR,A1\n", }, + +{ MINUS, ININT, + SHINT, ANYFIXED|TPOINT, + SONE, TANY, + NAREG|NASL, RESC1, + "\tldo\t-1(AL),A1\n", }, + +{ MINUS, ININT, + SHINT, ANYFIXED|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + "\tldo\t-CR(AL),A1\n", }, + +/* Simple reg->reg ops */ +{ OPSIMP, ININT, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tO\tAL,AR,A1\n", }, + +{ OPSIMP, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tO\tAL,AR,A1\n" + "\tO\tUL,UR,U1\n", }, + +/* + * The next rules handle all shift operators. + */ +/* (u)longlong left shift is emulated */ +{ LS, INLL, + SHLL|SCON, TLL, + SHINT|SCON, TINT, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "ZO", }, + +{ LS, ININT, + SHINT, ANYFIXED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\tzdep\tAL,31-AR,32-AR,A1\n", }, + +{ LS, ININT, + SHINT, ANYFIXED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tzvdep\tAL,32,A1\n", }, + +{ RS, INLL, + SHLL, TLONGLONG, + SCON, ANYFIXED, + NBREG|NBSL, RESC1, + "\tshd\tUL,AL,31-AR,A1\n" + "\textrs\tUL,31-AR,32,U1\n", }, + +{ RS, INLL, + SHLL, TULONGLONG, + SCON, ANYFIXED, + NBREG|NBSL, RESC1, + "\tshd\tUL,AL,AR,A1\n" + "\textru\tUL,31-AR,32,U1\n", }, + +/* (u)longlong right shift is emulated */ +{ RS, INLL, + SHLL|SCON, TLL, + SHINT|SCON, TINT, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "ZO", }, + +{ RS, ININT, + SHINT, ANYSIGNED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\textrs\tAL,31-AR,32,A1\n", }, + +{ RS, ININT, + SHINT, ANYUSIGNED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\textru\tAL,31-AR,32,A1\n", }, + +/* TODO the following should be split into mtsar and actual shift parts */ +{ RS, ININT, + SHINT, ANYSIGNED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tvextrs\tAL,32,A1\n", }, + +{ RS, ININT, + SHINT, ANYUSIGNED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tvextru\tAL,32,A1\n", }, + +/* + * The next rules takes care of assignments. "=". + */ + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SPCON, TANY, + 0, RDEST, + "\tldi\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TBYTE, + SHINT, TBYTE, + 0, RDEST, + "\tstb\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, THWORD, + SHINT, THWORD, + 0, RDEST, + "\tsth\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TWORD|TPOINT, + SHINT, TWORD|TPOINT, + 0, RDEST, + "\tstw\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SOREG, TLL, + SHLL, TLL, + 0, RDEST, + "\tstw\tAR,AL\n" + "\tstw\tUR,UL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, TBYTE, + SOREG, TBYTE, + 0, RDEST, + "\tldb\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, THWORD, + SOREG, THWORD, + 0, RDEST, + "\tldh\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, TWORD|TPOINT, + SOREG, TWORD|TPOINT, + 0, RDEST, + "\tldw\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SOREG, TLL, + 0, RDEST, + "\tldw\tAR,AL\n" + "\tldw\tUR,UL\n", }, + +{ ASSIGN, FOREFF|ININT, + SHINT, TWORD|TPOINT, + SHINT, TWORD|TPOINT, + 0, RDEST, + "\tcopy\tAR,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SHINT, ANYFIXED, + SHINT, ANYFIXED, + 0, RDEST, + "\tcopy\tAR,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SFLD, TANY, + SPICON, TANY, + 0, RDEST, + "\tdepi\tAR,31-H,S,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SFLD, TANY, + SHINT, TANY, + 0, RDEST, + "\tdep\tAR,31-H,S,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SHLL, TLL, + 0, RDEST, + "\tcopy\tAR,AL\n" + "\tcopy\tUR,UL\n", }, + +{ ASSIGN, FOREFF|INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + 0, RDEST, + "\tfcpy,sgl\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfcpy,dbl\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INFL, + SHFL, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + "\tfldws\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfldds\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INFL, + SOREG, TFLOAT, + SHFL, TFLOAT, + 0, RDEST, + "\tfstws\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SOREG, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfstds\tAR,AL\n", }, + +/* + * DIV/MOD/MUL + */ + +{ DIV, ININT, + SHINT, TWORD, + SHINT, TWORD, + NAREG, RESC1, + "ZO", }, + +{ DIV, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG, RESC1, + "ZO", }, + +{ DIV, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfdiv,sgl\tAL,AR,A1\n", }, + +{ DIV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfdiv,dbl\tAL,AR,A1\n", }, + +{ MOD, ININT, + SHINT, TWORD, + SHINT, TWORD, + NAREG, RESC1, + "ZO", }, + +{ MOD, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG, RESC1, + "ZO", }, + +{ MUL, ININT, + SHINT, TWORD, + SHINT, TWORD, + NAREG, RESC1, + "ZO", }, + +{ MUL, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG, RESC1, + "ZO", }, + +{ MUL, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfmul,sgl\tAL,AR,A1\n", }, + +{ MUL, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfmul,dbl\tAL,AR,A1\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INLL, + SANY, TANY, + SOREG, TLL, + NBREG, RESC1, + "\tldw\tAL,A1\n" + "\tldw\tUL,U1\n", }, + +{ UMUL, ININT, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +{ UMUL, ININT, + SANY, TANY, + SOREG, THWORD, + NAREG|NASL, RESC1, + "\tldh\tAL,A1\n", }, + +{ UMUL, ININT, + SANY, TANY, + SOREG, TBYTE, + NAREG|NASL, RESC1, + "\tldb\tAL,A1\n", }, + +{ UMUL, INDBL, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "\tfldds\tAL,A1\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TFLOAT, + NCREG|NCSL, RESC1, + "\tfldws\tAL,A1\n", }, + +/* + * Logical/branching operators + */ +{ OPLOG, FORCC, + SHLL, TLL, + SHLL, TLL, + 0, 0, + "ZD", }, + +{ OPLOG, FORCC, + SHINT, TWORD|TPOINT, + SPICON, TWORD|TPOINT, + 0, 0, + "\tcomib,O\tAR,AL,LC\n", }, + +{ OPLOG, FORCC, + SHINT, TWORD|TPOINT, + SHINT, TWORD|TPOINT, + 0, 0, + "\tcomb,O\tAR,AL,LC\n", }, + +{ OPLOG, FORCC, + SHFL, TFLOAT, + SHFL, TFLOAT, + 0, RESCC, + "\tfcmp,sgl,!O\tAR,AL\n" + "\tftest\n" + "\tb\tLC\n" + "\tnop", }, + +{ OPLOG, FORCC, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RESCC, + "\tfcmp,dbl,!O\tAR,AL\n" + "\tftest\n" + "\tb\tLC\n" + "\tnop", }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + "\tb\tLL\n\tnop\n", }, + +#ifdef GCC_COMPAT +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + "\tbv\t%r0(AL)\n\tnop\n", }, +#endif + + +/* + * Convert LTYPE to reg. + */ + +{ OPLTYPE, INAREG, + SAREG, TANY, + SNAME, TANY, + 0, RDEST, + "\taddil\tUR,gp\n", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SOREG, TLL, + NBREG|NBSL, RESC1, + "\tldw\tAL,A1\n" + "\tldw\tUL,U1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tcopy\tAL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SPCON, ANYFIXED, + NAREG, RESC1, + "\tldi\tAR,A1\n", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SPCON, TLL, + NAREG, RESC1, + "\tldi\tAR,A1\n" + "\tcopy\t%r0,U1\n", }, + +{ OPLTYPE, ININT, + SANY, TANY, + SCON, TWORD|TPOINT, + NAREG, RESC1, + "\tldil\tUR,A1\n" + "\tldo\tAR(A1),A1\n", }, + +{ OPLTYPE, INCREG, + SANY, TFLOAT, + SHFL, TFLOAT, + NCREG, RESC1, + "\tfldws\tAL,A1\n", }, + +{ OPLTYPE, INDREG, + SANY, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldds\tAL,A1\n", }, + +/* + * Negate a word. + */ +{ UMINUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL, RESC1, + "\tsub\t%r0,AL,A1\n" + "\tsubb\t%r0,UL,A1\n", }, + +{ UMINUS, ININT, + SHINT, TWORD, + SHINT, TWORD, + NAREG|NASL, RESC1, + "\tsub\t%r0,AL,A1\n", }, + +{ UMINUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL, RESC1, + "\tfsub,sgl\t%fr0,AL,A1\n", }, + +{ UMINUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "\tfsub,dbl\t%fr0,AL,A1\n", }, + +{ COMPL, INLL, + SHLL, TLL, + SANY, TANY, + NBREG|NBSL, RESC1, + "\tuaddcm\t%r0,AL,A1\n" + "\tuaddcm\t%r0,UL,U1\n", }, + +{ COMPL, ININT, + SHINT, ANYFIXED, + SANY, TANY, + NAREG|NASL, RESC1, + "\tuaddcm\t%r0,AL,A1\n", }, + +/* + * Arguments to functions. + */ +/* TODO */ + + + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NSPECIAL|NAREG, 0, + "ZF", }, + +/* + * struct field ops + */ +{ FLD, ININT, + SHINT, TANY, + SFLD, ANYSIGNED, + NAREG|NASL, RESC1, + "\textrs\tAL,31-H,S,A1\n", }, + +{ FLD, ININT, + SHINT, TANY, + SFLD, ANYUSIGNED, + NAREG|NASL, RESC1, + "\textru\tAL,31-H,S,A1\n", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, + FREE, FREE, + FREE, FREE, + FREE, FREE, + "HELP; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); |