/* $OpenBSD: local2.c,v 1.2 2008/04/11 20:45:52 stefan Exp $ */ /* * Copyright (c) 2008 David Crawshaw * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "pass1.h" #include "pass2.h" char * rnames[] = { /* "\%g0", always zero, removed due to 31-element class limit */ "\%g1", "\%g2", "\%g3", "\%g4", "\%g5", "\%g6", "\%g7", "\%o0", "\%o1", "\%o2", "\%o3", "\%o4", "\%o5", "\%o6", "\%o7", "\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7", "\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7", "\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7", "\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15", "\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23", "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30", /*, "\%f31" XXX removed due to 31-element class limit */ "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14", "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30", "\%sp", "\%fp", }; void deflab(int label) { printf(LABFMT ":\n", label); } void prologue(struct interpass_prolog *ipp) { int i, stack; stack = V9RESERVE + V9STEP(p2maxautooff); for (i=ipp->ipp_regs; i; i >>= 1) if (i & 1) stack += 16; /* TODO printf("\t.proc %d\n"); */ printf("\t.global %s\n", ipp->ipp_name); printf("\t.align 4\n"); printf("%s:\n", ipp->ipp_name); if (SIMM13(stack)) printf("\tsave %%sp,-%d,%%sp\n", stack); else { printf("\tsetx -%d,%%g4,%%g1\n", stack); printf("\tsave %%sp,%%g1,%%sp\n"); } } void eoftn(struct interpass_prolog *ipp) { printf("\tret\n"); printf("\trestore\n"); printf("\t.type %s,#function\n", ipp->ipp_name); printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name); } void hopcode(int f, int o) { char *str; switch (o) { case EQ: str = "brz"; break; case NE: str = "brnz"; break; case ULE: case LE: str = "brlez"; break; case ULT: case LT: str = "brlz"; break; case UGE: case GE: str = "brgez"; break; case UGT: case GT: str = "brgz"; break; case PLUS: str = "add"; break; case MINUS: str = "sub"; break; case AND: str = "and"; break; case OR: str = "or"; break; case ER: str = "xor"; break; default: comperr("unknown hopcode: %d (with %c)", o, f); return; } printf("%s%c", str, f); } int tlen(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: return (SZINT / SZCHAR); case LONG: case ULONG: case LONGLONG: case ULONGLONG: return SZLONGLONG / SZCHAR; default: if (!ISPTR(p->n_type)) comperr("tlen type unknown: %d"); return SZPOINT(p->n_type) / SZCHAR; } } void zzzcode(NODE * p, int c) { char *str; NODE *l, *r; l = p->n_left; r = p->n_right; switch (c) { case 'A': /* Add const. */ if (ISPTR(l->n_type) && l->n_rval == FP) r->n_lval += V9BIAS; if (SIMM13(r->n_lval)) expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n"); else expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n" "\tadd AL,A2,A1\n"); break; case 'B': /* Subtract const. */ if (ISPTR(l->n_type) && l->n_rval == FP) r->n_lval -= V9BIAS; if (SIMM13(r->n_lval)) expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n"); else expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n" "\tsub AL,A2,A1\n"); break; case 'C': /* Load constant to register. */ if (ISPTR(p->n_type)) expand(p, 0, "\tsethi %h44(AL),A1\t\t! load label\n" "\tor A1,%m44(AL),A1\n" "\tsllx A1,12,A1\n" "\tor A1,%l44(AL),A1\n"); else if (SIMM13(p->n_lval)) expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n"); else expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n"); break; case 'F': /* Floating-point comparison, cf. hopcode(). */ switch (p->n_op) { case EQ: str = "fbe"; break; case NE: str = "fbne"; break; case ULE: case LE: str = "fbule"; break; case ULT: case LT: str = "fbul"; break; case UGE: case GE: str = "fbuge"; break; case UGT: case GT: str = "fbug"; break; /* XXX case PLUS: str = "add"; break; case MINUS: str = "sub"; break; case AND: str = "and"; break; case OR: str = "or"; break; case ER: str = "xor"; break;*/ default: comperr("unknown float code: %d", p->n_op); return; } printf(str); break; case 'Q': /* Structure assignment. */ /* TODO Check if p->n_stsize is small and use a few ldx's to move the struct instead of memcpy. The equiv. could be done on all the architectures. */ if (l->n_rval != O0) printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]); if (SIMM13(p->n_stsize)) printf("\tor %%g0,%d,%%o2\n", p->n_stsize); else printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize); printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n"); printf("\tnop\n"); break; default: cerror("unknown zzzcode call: %c", c); } } int rewfld(NODE * p) { return (1); } int fldexpand(NODE *p, int cookie, char **cp) { printf("XXX fldexpand called\n"); /* XXX */ return 1; } int flshape(NODE * p) { return SRREG; } int shtemp(NODE * p) { return 0; } void adrcon(CONSZ val) { } void conput(FILE * fp, NODE * p) { if (p->n_op != ICON) { comperr("conput got bad op: %s", copst(p->n_op)); return; } if (p->n_name[0] != '\0') { fprintf(fp, "%s", p->n_name); if (p->n_lval > 0) fprintf(fp, "+"); if (p->n_lval) fprintf(fp, "%lld", p->n_lval); } else fprintf(fp, CONFMT, p->n_lval); } void insput(NODE * p) { comperr("insput"); } void upput(NODE *p, int size) { comperr("upput"); } void adrput(FILE * io, NODE * p) { int64_t off; if (p->n_op == FLD) { printf("adrput a FLD\n"); p = p->n_left; } if (p->n_op == UMUL && p->n_right == 0) p = p->n_left; off = p->n_lval; switch (p->n_op) { case NAME: if (p->n_name[0] != '\0') fputs(p->n_name, io); if (off > 0) fprintf(io, "+"); if (off != 0) fprintf(io, CONFMT, off); return; case OREG: fprintf(io, "%s", rnames[p->n_rval]); if (p->n_rval == FP) off += V9BIAS; if (p->n_rval == SP) off += V9BIAS + V9RESERVE; if (off > 0) fprintf(io, "+"); if (off) fprintf(io, "%lld", off); return; case ICON: /* addressable value of the constant */ conput(io, p); return; case REG: fputs(rnames[p->n_rval], io); return; case FUNARG: /* We do something odd and store the stack offset in n_rval. */ fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval); return; default: comperr("bad address, %s, node %p", copst(p->n_op), p); return; } } void cbgen(int o, int lab) { } void myreader(struct interpass * ipole) { } void mycanon(NODE * p) { } void myoptim(struct interpass * ipole) { } void rmove(int s, int d, TWORD t) { printf("\tmov %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]); } int gclass(TWORD t) { if (t == FLOAT) return CLASSB; if (t == DOUBLE) return CLASSC; return CLASSA; } void lastcall(NODE *p) { } int special(NODE *p, int shape) { return SRNOPE; } void mflags(char *str) { } int COLORMAP(int c, int *r) { int num=0; switch (c) { case CLASSA: num += r[CLASSA]; return num < 32; case CLASSB: num += r[CLASSB]; num += 2*r[CLASSC]; return num < 32;; case CLASSC: num += r[CLASSC]; num += 2*r[CLASSB]; return num < 17; case CLASSD: return 0; default: comperr("COLORMAP: unknown class: %d", c); return 0; } }