/* pentConst - stuff to code constants for the pentium. */ #include "common.h" #include "hash.h" #include "pfToken.h" #include "isx.h" #include "pfPreamble.h" #include "pentConst.h" char *pentFloatOrLongLabel(char *buf, int bufSize, enum isxValType valType, struct isxAddress *iad) /* Return label associated with floating point or long constant. */ { if (valType == ivLong) safef(buf, bufSize, "Q%lld", iad->val.isxTok.val.l); else { char pre = (valType == ivFloat ? 'F' : 'D'); safef(buf, bufSize, "%c%g", pre, iad->val.isxTok.val.x); subChar(buf, '-', '_'); subChar(buf, '.', 'o'); } return buf; } static void printAsciiString(char *s, FILE *f) /* Print constant string with escapes for assembler * The surrounding quotes and terminal 0 are handled elsewhere. */ { char c; while ((c = *s++) != 0) { switch (c) { case '"': case '\\': fputc('\\', f); fputc(c, f); break; default: if (isprint(c)) fputc(c, f); else { fputc('\\', f); fprintf(f, "%o", c); } break; } } } static void pentPrintInitConst(char *prefix, char *label, enum isxValType valType, struct isxToken *tok, FILE *f) /* Print out a constant initialization */ { union pfTokVal val = tok->val; switch (valType) { case ivByte: fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.byte\t%d\n", val.i); break; case ivShort: fprintf(f, "\t.align 1\n"); fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.word\t%d\n", val.i); break; case ivInt: fprintf(f, "\t.align 2\n"); fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.long\t%d\n", val.i); break; case ivLong: fprintf(f, "\t.align 3\n"); fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.long\t%d\n", (int)(val.l&0xFFFFFFFF)); fprintf(f, "\t.long\t%d\n", (int)(val.l>>32)); break; case ivFloat: { float x = val.x; _pf_Int *i = (_pf_Int *)(&x); fprintf(f, "\t.align 2\n"); fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.long\t%d\n", *i); break; } case ivDouble: { _pf_Long *l = (_pf_Long *)(&val.x); fprintf(f, "\t.align 3\n"); fprintf(f, "%s%s:\n", prefix, label); fprintf(f, "\t.long\t%d\n", (int)(*l&0xFFFFFFFF)); fprintf(f, "\t.long\t%d\n", (int)(*l>>32)); break; } case ivString: fprintf(f, "\t.cstring\n"); fprintf(f, "\t.ascii\t\""); printAsciiString(val.s, f); fprintf(f, "\\0\"\n"); fprintf(f, "\t.data\n"); break; default: internalErr(); break; } } static void codeStringConst(char *s, struct hash *stringHash, FILE *f) /* If s is not in stringHash, then write out constant initialization and * save label of initialized data in stringHash */ { if (!hashLookup(stringHash, s)) { char label[16]; int len = strlen(s); safef(label, sizeof(label), "STR%d", stringHash->elCount); fprintf(f, "\t.cstring\n"); fprintf(f, "%sS:\n", label); fprintf(f, "\t.ascii\t\""); printAsciiString(s, f); fprintf(f, "\\0\"\n"); fprintf(f, "\t.data\n"); fprintf(f, "\t.align\t2\n"); fprintf(f, "%s:\n", label); fprintf(f, "\t.long\t0\n"); fprintf(f, "\t.long\t0\n"); fprintf(f, "\t.long\t%sS\n", label); fprintf(f, "\t.long\t%d\n", len); fprintf(f, "\t.long\t%d\n", len); fprintf(f, "\t.byte\t1\n"); hashAdd(stringHash, s, cloneString(label)); } } static void codeLocalConst(struct isxAddress *iad, struct hash *uniqHash, struct hash *stringHash, boolean *pInText, FILE *f) /* Print code that helps local non-int constant initialization. */ { if (iad->adType == iadConst) { char buf[64]; enum isxValType valType = iad->valType; struct hashEl *hel; switch (valType) { case ivFloat: case ivDouble: case ivLong: pentFloatOrLongLabel(buf, sizeof(buf), valType, iad); if ((hel = hashLookup(uniqHash, buf)) == NULL) { if (*pInText) { fprintf(f, "\t.data\n"); *pInText = FALSE; } pentPrintInitConst("", buf, valType, &iad->val.isxTok, f); hel = hashAdd(uniqHash, buf, NULL); } iad->name = hel->name; break; case ivString: codeStringConst(iad->val.isxTok.val.s, stringHash, f); break; } } } void pentCodeLocalConsts(struct isxList *isxList, struct hash *uniqHash, struct hash *stringHash, FILE *f) /* Print code that helps local non-int constant initialization. * for any sources in instruction. */ { struct dlNode *node; boolean inText = TRUE; fprintf(f, "#String, float, double, and long constants\n"); for (node = isxList->iList->head; !dlEnd(node); node = node->next) { struct isx *isx = node->val; if (isx->left) codeLocalConst(isx->left, uniqHash, stringHash, &inText, f); if (isx->right) codeLocalConst(isx->right, uniqHash, stringHash, &inText, f); } fprintf(f, "\n"); if (!inText) fprintf(f, "\t.text\n"); }