/* * Create a reference for an extern variable or function. */ static NODE * picext(NODE *p) { #if defined(ELFABI) NODE *q; struct symtab *sp; char *c; if (p->n_sp->sflags & SBEENHERE) return p; c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); sp = picsymtab("", c, "@GOTPCREL"); sp->sflags |= SBEENHERE; q = block(NAME, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap); q->n_sp = sp; q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); q->n_sp = sp; nfree(p); return q; #elif defined(MACHOABI) return p; #endif }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { static char *loctbl[] = { "text", "data", "data" }; TWORD t; char *n; int s; if (sp == NULL) { lastloc = -1; return; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); n = sp->soname ? sp->soname : exname(sp->sname); if (sp->sclass == EXTDEF) printf(" .globl %s\n", n); if (ISFTN(sp->stype) || talign(sp->stype, sp->ssue) > ALCHAR) printf(".even\n"); if (sp->slevel == 0) { printf("%s:\n", n); } else { printf(LABFMT ":\n", sp->soffset); } }
/* * Create a reference for an extern variable or function. */ static NODE * picext(NODE *p) { #if defined(ELFABI) struct attr *ga; NODE *q; struct symtab *sp; char *c; if (p->n_sp->sflags & SBEENHERE) return p; if ((ga = attr_find(p->n_sp->sap, GCC_ATYP_VISIBILITY)) && strcmp(ga->sarg(0), "hidden") == 0) return p; /* no GOT reference */ c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); sp = picsymtab("", c, "@GOTPCREL"); sp->sflags |= SBEENHERE; q = block(NAME, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap); q->n_sp = sp; q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); q->n_sp = sp; nfree(p); return q; #elif defined(MACHOABI) return p; #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; printf(" .comm %s,0%o\n", exname(q->soname), off); }
/* * Called when a identifier has been declared, to give target last word. */ void fixdef(struct symtab *sp) { if ((constructor || destructor) && (sp->sclass != PARAM)) { printf("\t.section .%ctors,\"aw\",@progbits\n", constructor ? 'c' : 'd'); printf("\t.p2align 2\n"); printf("\t.long %s\n", exname(sp->sname)); printf("\t.previous\n"); constructor = destructor = 0; } }
/* 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) printf(" .lcomm %s,0%o\n", exname(q->soname), off); else printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off); }
/* * Print out the prolog assembler. */ void prologue(struct interpass_prolog * ipp) { int addto; int i, j; ftype = ipp->ipp_type; printf("\t.align 2\n"); if (ipp->ipp_vis) printf("\t.globl %s\n", ipp->ipp_name); printf("\t.ent %s\n", ipp->ipp_name); printf("%s:\n", ipp->ipp_name); addto = offcalc(ipp); /* for the moment, just emit this PIC stuff - NetBSD does it */ printf("\t.frame %s,%d,%s\n", rnames[FP], ARGINIT/SZCHAR, rnames[RA]); printf("\t.set noreorder\n"); printf("\t.cpload $25\t# pseudo-op to load GOT ptr into $25\n"); printf("\t.set reorder\n"); printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], ARGINIT/SZCHAR); /* for the moment, just emit PIC stuff - NetBSD does it */ printf("\t.cprestore 8\t# pseudo-op to store GOT ptr at 8(sp)\n"); printf("\tsw %s,4(%s)\n", rnames[RA], rnames[SP]); printf("\tsw %s,(%s)\n", rnames[FP], rnames[SP]); printf("\tmove %s,%s\n", rnames[FP], rnames[SP]); #ifdef notyet /* profiling */ if (pflag) { printf("\t.set noat\n"); printf("\tmove %s,%s\t# save current return address\n", rnames[AT], rnames[RA]); printf("\tsubu %s,%s,8\t# _mcount pops 2 words from stack\n", rnames[SP], rnames[SP]); printf("\tjal %s\n", exname("_mcount")); printf("\tnop\n"); printf("\t.set at\n"); } #endif if (addto) printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], addto); for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) if (i & 1) fprintf(stdout, "\tsw %s,-%d(%s) # save permanent\n", rnames[j], regoff[j], rnames[FP]); }
/* make a common declaration for id, if reasonable */ void defzero(struct symtab *sp) { int off; off = tsize(sp->stype, sp->sdf, sp->sap); off = (off+(SZCHAR-1))/SZCHAR; printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); if (sp->slevel == 0) printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off); else printf(LABFMT ",0%o\n", sp->soffset, off); }
/* * Push a structure on stack as argument. */ static void starg(NODE *p) { //assert(p->n_rval == A1); printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], p->n_stsize); /* A0 = dest, A1 = src, A2 = len */ printf("\tmove %s,%s\n", rnames[A0], rnames[SP]); printf("\tli %s,%d\t# structure size\n", rnames[A2], p->n_stsize); printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); printf("\tjal %s\t# structure copy\n", exname("memcpy")); printf("\tnop\n"); printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); }
/* * Push a structure on stack as argument. */ static void starg(NODE *p) { int sz = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0); //assert(p->n_rval == A1); printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], sz); /* A0 = dest, A1 = src, A2 = len */ printf("\tmove %s,%s\n", rnames[A0], rnames[SP]); printf("\tli %s,%d\t# structure size\n", rnames[A2], sz); printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); printf("\tjal %s\t# structure copy\n", exname("memcpy")); printf("\tnop\n"); printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); }
/* * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines */ static void emulop(NODE *p) { char *ch = NULL; if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3"; else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG || DEUNSIGN(p->n_type) == INT)) ch = "ashlsi3"; else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3"; else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT)) ch = "lshrsi3"; else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3"; else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT)) ch = "ashrsi3"; else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT)) ch = "divsi3"; else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; else if (p->n_op == DIV && (p->n_type == ULONG || p->n_type == UNSIGNED)) ch = "udivsi3"; else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT)) ch = "modsi3"; else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; else if (p->n_op == MOD && (p->n_type == ULONG || p->n_type == UNSIGNED)) ch = "umodsi3"; else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT)) ch = "mulsi3"; else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2"; else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2"; else ch = 0, comperr("ZE"); printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); printf("\tjal __%s\t# emulated operation\n", exname(ch)); printf("\tnop\n"); printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sclass == EXTDEF) { printf(" .globl %s\n", name); } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Called when a identifier has been declared. */ void fixdef(struct symtab *sp) { struct attr *ga; #ifdef HAVE_WEAKREF /* not many as'es have this directive */ if ((ga = attr_find(sp->sap, GCC_ATYP_WEAKREF)) != NULL) { char *wr = ga->sarg(0); char *sn = getsoname(sp); if (wr == NULL) { if ((ga = attr_find(sp->sap, GCC_ATYP_ALIAS))) { wr = ga->sarg(0); } } if (wr == NULL) printf("\t.weak %s\n", sn); else printf("\t.weakref %s,%s\n", sn, wr); } else if ((ga = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) { char *an = ga->sarg(0); char *sn = getsoname(sp); char *v; v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl"; printf("\t.%s %s\n", v, sn); printf("\t.set %s,%s\n", sn, an); } if (alias != NULL && (sp->sclass != PARAM)) { char *name = getexname(sp); printf("\t.globl %s\n", name); printf("%s = ", name); printf("%s\n", exname(alias)); alias = NULL; } if ((constructor || destructor) && (sp->sclass != PARAM)) { NODE *p = p1alloc(); p->n_op = NAME; p->n_sp = (struct symtab *)(constructor ? "constructor" : "destructor"); sp->sap = attr_add(sp->sap, gcc_attr_parse(p)); constructor = destructor = 0; } #endif }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *n; n = sp->soname ? sp->soname : exname(sp->sname); #ifdef USE_GAS if (ISFTN(t)) printf("\t.type %s,%%function\n", n); #endif if (sp->sclass == EXTDEF) printf("\t.global %s\n", n); if (sp->slevel == 0) printf("%s:\n", n); else printf(LABFMT ":\n", sp->soffset); }
/* * Do name mangling of a symbol table entry. * The resulting name is saved in soname. */ char * decoratename(struct symtab *sp, int type) { char *n; #define QNM(m,s) case m: n = s; break switch (type) { QNM(NM_NEW,"_Znwm"); QNM(NM_NWA,"_Znam"); QNM(NM_DEL,"_ZdlPv"); QNM(NM_DLA,"_ZdaPv"); case NM_NORMAL: /* Defined in defid() */ break; default: uerror("missed mangling %d\n", type); return ""; } if (type != NM_NORMAL) return addname(n); /* special non-mangled cases: * "C" linkage * main() function * variables outside namespaces and classes */ if (elnk == LINK_C || strcmp(sp->sname, "main") == 0 || (sp->sdown == spole && ISFTN(sp->stype) == 0)) { n = exname(sp->sname); return addname(n); } /* Compute the mangled name for other symbols */ nmptr = 0; subptr = 0; nmch('_'); nmch('Z'); if (sp->sdown != NULL) { nmch('N'); recnpsh(sp->sdown); } pshsln(sp->sname); if (sp->sdown != NULL) nmch('E'); if (ISFTN(sp->stype) && sp->sdf->dfun) pshargs(sp->sdf->dfun); nmch(0); return addname(nmblk); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); printf("\t.type %s,@%s\n", name, ISFTN(sp->stype)? "function" : "object"); } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Structure assignment. */ static void stasg(NODE *p) { assert(p->n_right->n_rval == A1); /* A0 = dest, A1 = src, A2 = len */ printf("\tli %s,%d\t# structure size\n", rnames[A2], p->n_stsize); if (p->n_left->n_op == OREG) { printf("\taddiu %s,%s," CONFMT "\t# dest address\n", rnames[A0], rnames[p->n_left->n_rval], p->n_left->n_lval); } else if (p->n_left->n_op == NAME) { printf("\tla %s,", rnames[A0]); adrput(stdout, p->n_left); printf("\n"); } printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); printf("\tjal %s\t# structure copy\n", exname("memcpy")); printf("\tnop\n"); printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { static char *loctbl[] = { "text", "data", "data" }; TWORD t; char *n; int s; t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; n = sp->soname ? sp->soname : exname(sp->sname); if (sp->sclass == EXTDEF) printf(" .globl %s\n", n); if (sp->slevel == 0) { printf("%s:\n", n); } else { printf(LABFMT ":\n", sp->soffset); } }
void defloc(struct symtab *sp) { TWORD t; char *name; t = sp->stype; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (!ISFTN(t)) { printf("\t.type %s,#object\n", name); printf("\t.size %s," CONFMT "\n", name, tsize(sp->stype, sp->sdf, sp->sap) / SZCHAR); } if (sp->sclass == EXTDEF) printf("\t.global %s\n", name); if (sp->slevel == 0) { printf("%s:\n", name); } else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); if (ISFTN(sp->stype)) { printf("\t.type %s,@function\n", name); } else { printf("\t.type %s,@object\n", name); printf("\t.size %s,%d\n", name, (int)tsize(sp->stype, sp->sdf, sp->sap)/SZCHAR); } } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * print out a constant node * mat be associated with a label */ int ninval(NODE *p) { struct symtab *q; TWORD t; p = p->n_left; t = p->n_type; if (t > BTMASK) t = p->n_type = INT; /* pointer */ switch (t) { case LONGLONG: case ULONGLONG: inval(p->n_lval & 0xffffffff); inval(p->n_lval >> 32); break; case LONG: case ULONG: 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)) { printf("+" LABFMT, q->soffset); } else printf("+%s", exname(q->soname)); } printf("\n"); break; default: fwalk(p, eprint, 0); return 0; } return 1; }
/* * print out a constant node * mat be associated with a label */ int ninval(NODE *p) { struct symtab *q; TWORD t; p = p->n_left; t = p->n_type; if (t > BTMASK) p->n_type = t = INT; /* pointer */ if (p->n_op != ICON) cerror("ninval: init node not constant"); switch (t) { case LONG: case ULONG: inval(p->n_lval & 0xffff); inval(p->n_lval >> 16); break; case INT: case UNSIGNED: printf("\t.word 0%o", (short)p->n_lval); if ((q = p->n_sp) != NULL) { if ((q->sclass == STATIC && q->slevel > 0)) { printf("+" LABFMT, q->soffset); } else printf("+%s", exname(q->soname)); } printf("\n"); break; default: return 0; } return 1; }
/* make a common declaration for id, if reasonable */ void defzero(struct symtab *sp) { int off, al; char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); off = tsize(sp->stype, sp->sdf, sp->sap); SETOFF(off,SZCHAR); off /= SZCHAR; al = talign(sp->stype, sp->sap)/SZCHAR; if (sp->sclass == STATIC) { if (sp->slevel == 0) { printf("\t.local %s\n", name); } else printf("\t.local " LABFMT "\n", sp->soffset); } if (sp->slevel == 0) { printf("\t.comm %s,0%o,%d\n", name, off, al); } else printf("\t.comm " LABFMT ",0%o,%d\n", sp->soffset, off, al); }
/* * http://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Soft-float-library-routines */ static void fpemulop(NODE *p) { NODE *l = p->n_left; char *ch = NULL; if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3"; else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3"; else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3"; else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3"; else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2"; else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2"; else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2"; else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2"; else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2"; else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2"; else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2"; else if (p->n_op == SCONV && p->n_type == FLOAT) { if (l->n_type == DOUBLE) ch = "truncdfsf2"; else if (l->n_type == LDOUBLE) ch = "trunctfsf2"; else if (l->n_type == ULONGLONG) ch = "floatdisf"; /**/ else if (l->n_type == LONGLONG) ch = "floatdisf"; else if (l->n_type == LONG) ch = "floatsisf"; else if (l->n_type == ULONG) ch = "floatunsisf"; else if (l->n_type == INT) ch = "floatsisf"; else if (l->n_type == UNSIGNED) ch = "floatunsisf"; } else if (p->n_op == SCONV && p->n_type == DOUBLE) { if (l->n_type == FLOAT) ch = "extendsfdf2"; else if (l->n_type == LDOUBLE) ch = "trunctfdf2"; else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; else if (l->n_type == LONGLONG) ch = "floatdidf"; else if (l->n_type == LONG) ch = "floatsidf"; else if (l->n_type == ULONG) ch = "floatunsidf"; else if (l->n_type == INT) ch = "floatsidf"; else if (l->n_type == UNSIGNED) ch = "floatunsidf"; } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { if (l->n_type == FLOAT) ch = "extendsftf2"; else if (l->n_type == DOUBLE) ch = "extenddfdf2"; else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; else if (l->n_type == LONGLONG) ch = "floatdidf"; else if (l->n_type == LONG) ch = "floatsidf"; else if (l->n_type == ULONG) ch = "floatunssidf"; else if (l->n_type == INT) ch = "floatsidf"; else if (l->n_type == UNSIGNED) ch = "floatunsidf"; } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { if (l->n_type == FLOAT) ch = "fixunssfdi"; else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; } else if (p->n_op == SCONV && p->n_type == LONGLONG) { if (l->n_type == FLOAT) ch = "fixsfdi"; else if (l->n_type == DOUBLE) ch = "fixdfdi"; else if (l->n_type == LDOUBLE) ch = "fixdfdi"; } else if (p->n_op == SCONV && p->n_type == LONG) { if (l->n_type == FLOAT) ch = "fixsfsi"; else if (l->n_type == DOUBLE) ch = "fixdfsi"; else if (l->n_type == LDOUBLE) ch = "fixdfsi"; } else if (p->n_op == SCONV && p->n_type == ULONG) { if (l->n_type == FLOAT) ch = "fixunssfsi"; else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; } else if (p->n_op == SCONV && p->n_type == INT) { if (l->n_type == FLOAT) ch = "fixsfsi"; else if (l->n_type == DOUBLE) ch = "fixdfsi"; else if (l->n_type == LDOUBLE) ch = "fixdfsi"; } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { if (l->n_type == FLOAT) ch = "fixunssfsi"; else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; } if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); if (p->n_op == SCONV) { if (l->n_type == FLOAT) { printf("\tmfc1 %s,", rnames[A0]); adrput(stdout, l); printf("\n\tnop\n"); } else if (l->n_type == DOUBLE || l->n_type == LDOUBLE) { printf("\tmfc1 %s,", rnames[A1]); upput(l, 0); printf("\n\tnop\n"); printf("\tmfc1 %s,", rnames[A0]); adrput(stdout, l); printf("\n\tnop\n"); } } else { comperr("ZF: incomplete softfloat - put args in registers"); } printf("\tjal __%s\t# softfloat operation\n", exname(ch)); printf("\tnop\n"); if (p->n_op >= EQ && p->n_op <= GT) printf("\tcmp %s,0\n", rnames[V0]); }
/* * print out a constant node * mat be associated with a label */ int ninval(CONSZ off, int fsz, NODE *p) { union { float f; double d; int i[2]; } u; struct symtab *q; TWORD t; #ifndef USE_GAS int i, j; #endif t = p->n_type; if (t > BTMASK) p->n_type = t = INT; /* pointer */ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) uerror("element not constant"); switch (t) { case LONGLONG: case ULONGLONG: #ifdef USE_GAS printf("\t.dword %lld\n", (long long)p->n_lval); #else i = p->n_lval >> 32; j = p->n_lval & 0xffffffff; p->n_type = INT; if (bigendian) { p->n_lval = j; ninval(off, 32, p); p->n_lval = i; ninval(off+32, 32, p); } else { p->n_lval = i; ninval(off, 32, p); p->n_lval = j; ninval(off+32, 32, p); } #endif break; case INT: case UNSIGNED: printf("\t.word " CONFMT, (CONSZ)p->n_lval); if ((q = p->n_sp) != NULL) { if ((q->sclass == STATIC && q->slevel > 0)) { printf("+" LABFMT, q->soffset); } else printf("+%s", q->soname ? q->soname : exname(q->sname)); } printf("\n"); break; case SHORT: case USHORT: astypnames[SHORT] = astypnames[USHORT] = "\t.half"; return 0; case LDOUBLE: case DOUBLE: u.d = (double)p->n_dcon; if (bigendian) { printf("\t.word\t%d\n", u.i[0]); printf("\t.word\t%d\n", u.i[1]); } else { printf("\t.word\t%d\n", u.i[1]); printf("\t.word\t%d\n", u.i[0]); } break; case FLOAT: u.f = (float)p->n_dcon; printf("\t.word\t0x%x\n", u.i[0]); break; default: return 0; } return 1; }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { extern char *nextsect; static char *loctbl[] = { "text", "data", "section .rodata" }; extern int tbss; char *name; TWORD t; int s; if (sp == NULL) { lastloc = -1; return; } if (kflag) { #ifdef MACHOABI loctbl[DATA] = "section .data.rel.rw,\"aw\""; loctbl[RDATA] = "section .data.rel.ro,\"aw\""; #else loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits"; loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits"; #endif } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sflags & STLS) { if (s != DATA) cerror("non-data symbol in tls section"); if (tbss) nextsect = ".tbss,\"awT\",@nobits"; else nextsect = ".tdata,\"awT\",@progbits"; tbss = 0; lastloc = -1; } varattrib(name, sp->sap); if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); s = ISFTN(t) ? ALINT : talign(t, sp->sap); if (s > ALCHAR) printf(" .align %d\n", s/ALCHAR); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); #ifndef MACHOABI printf("\t.type %s,@%s\n", name, ISFTN(t)? "function" : "object"); #endif } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { extern char *nextsect; static char *loctbl[] = { "text", "data", "section .rodata" }; extern int tbss; int weak = 0; char *name; TWORD t; int s; if (sp == NULL) { lastloc = -1; return; } if (kflag) { loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits"; loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits"; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sflags & STLS) { if (s != DATA) cerror("non-data symbol in tls section"); if (tbss) nextsect = ".tbss,\"awT\",@nobits"; else nextsect = ".tdata,\"awT\",@progbits"; tbss = 0; lastloc = -1; } #ifdef GCC_COMPAT { struct attr *ga; if ((ga = attr_find(sp->sap, GCC_ATYP_SECTION)) != NULL) nextsect = ga->sarg(0); if ((ga = attr_find(sp->sap, GCC_ATYP_WEAK)) != NULL) weak = 1; if (attr_find(sp->sap, GCC_ATYP_DESTRUCTOR)) { printf("\t.section\t.dtors,\"aw\",@progbits\n"); printf("\t.align 8\n\t.quad\t%s\n", name); lastloc = -1; } if (attr_find(sp->sap, GCC_ATYP_CONSTRUCTOR)) { printf("\t.section\t.ctors,\"aw\",@progbits\n"); printf("\t.align 8\n\t.quad\t%s\n", name); lastloc = -1; } if ((ga = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) && strcmp(ga->sarg(0), "default")) printf("\t.%s %s\n", ga->sarg(0), name); } #endif if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); s = ISFTN(t) ? ALINT : talign(t, sp->sap); if (s > ALCHAR) printf(" .align %d\n", s/ALCHAR); if (weak) printf(" .weak %s\n", name); else if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); printf("\t.type %s,@%s\n", name, ISFTN(t)? "function" : "object"); } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }