home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)primitives.c 1.12 1/20/89
- */
- #include "datadesc.h"
- #include "builtins.h"
- #include "error.h"
- #include "nodes.h"
- #include "regdefs.h"
- #include "genutils.h"
- #include "emit.h"
- #include "consts.h"
- #include "evaluate.h"
- #include "primitives.h"
- #include "system.h"
- #include "trace.h"
-
- NodePtr theNode = NULL;
- extern char *codeFileName;
- Boolean formatAs0r = FALSE;
-
- static void unimplementedPrimitive(opIndex, typeIndex)
- int opIndex, typeIndex;
- {
- emit("Primitive %d of type %d\n", opIndex, typeIndex);
- ErrorMessage(theNode, "Unimplemented primitive %d of type %d", opIndex, typeIndex);
- }
-
- void implementationBug(string)
- char *string;
- {
- emit("Implementation bug (%s): %s\n", codeFileName, string);
- ErrorMessage(theNode, "Implementation bug (%s): %s", codeFileName, string);
- }
-
- #define SELF 1
- #define ARG1 2
- #define ARG2 4
- #define ARG3 8
- #define S SELF
- #define S1 (SELF | ARG1)
- #define S12 (SELF | ARG1 | ARG2)
- #ifdef vax
- #define T FALSE
- #endif
- #ifdef sun
- #define T TRUE
- #endif
- #define F FALSE
-
- PrimitiveDesc primitives[] =
- {
- /* None for abstract type */
- /* None for any */
- /* Array 1 */
- { 2, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
- { 102, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
- { 202, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
- { 302, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
- { 402, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
- { 502, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
- { 602, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "slideTo", F, 0 },
- { 702, FALSE, ANYINDEX, NILINDEX, NILINDEX, "addUpper", F, 0 },
- { 802, TRUE , ANYINDEX, NILINDEX, NILINDEX, "removeUpper", F, 0 },
- { 902, FALSE, ANYINDEX, NILINDEX, NILINDEX, "addLower", F, 0 },
- {1002, TRUE , ANYINDEX, NILINDEX, NILINDEX, "removeLower", F, 0 },
- {1102, TRUE , BOOLEANINDEX, NILINDEX, NILINDEX, "empty", F, 0 },
- {1202, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
- /* Boolean 3 */
- { 3, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, ">", F, 0 },
- { 103, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, ">=", F, 0 },
- { 203, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "<", F, 0 },
- { 303, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "<=", F, 0 },
- { 403, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "=", F, 0 },
- { 503, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "!=", F, 0 },
- { 603, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "&", F, S1 },
- { 703, TRUE , BOOLEANINDEX, BOOLEANINDEX, NILINDEX, "|", F, S1 },
- { 803, TRUE , BOOLEANINDEX, NILINDEX, NILINDEX, "!", F, S },
- { 903, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- /* Character 4 */
- { 4, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, ">", F, 0 },
- { 104, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, ">=", F, 0 },
- { 204, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "<", F, 0 },
- { 304, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "<=", F, 0 },
- { 404, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "=", F, 0 },
- { 504, TRUE , BOOLEANINDEX, CHARACTERINDEX, NILINDEX, "!=", F, 0 },
- { 604, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- { 704, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "ord", F, 0 },
- { 804, TRUE , CHARACTERINDEX,INTEGERINDEX, NILINDEX, "literal", F, 0 },
- /* Condition 5 */
- { 5, TRUE , CONDITIONINDEX, NILINDEX, NILINDEX, "create on type", F, 0 },
- /* Integer 6 */
- { 6, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "+", F, S1 },
- { 106, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "-", F, S1 },
- { 206, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "*", T, S1 },
- { 306, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "/", T, S1 },
- { 406, TRUE , INTEGERINDEX, INTEGERINDEX, NILINDEX, "#", T, S1 },
- { 506, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, ">", F, 0 },
- { 606, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, ">=", F, 0 },
- { 706, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "<", F, 0 },
- { 806, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "<=", F, 0 },
- { 906, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "=", F, 0 },
- {1006, TRUE , BOOLEANINDEX, INTEGERINDEX, NILINDEX, "!=", F, 0 },
- {1106, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- {1206, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "~", F, S },
- {1306, TRUE , REALINDEX, NILINDEX, NILINDEX, "asReal", F, S },
- /* None for NIL 7 */
- /* Node 8 */
- { 8, FALSE, TIMEINDEX, NILINDEX, NILINDEX, "delay", F, 0 },
- { 108, FALSE, TIMEINDEX, NILINDEX, NILINDEX, "waitUntil", F, 0 },
- { 208, TRUE , NODELISTINDEX, NILINDEX, NILINDEX, "getActiveNodes", F, 0 },
- { 308, TRUE , NODELISTINDEX, NILINDEX, NILINDEX, "getAllNodes", F, 0 },
- { 408, TRUE , NODELISTELEMENTINDEX, NODEINDEX, NILINDEX, "getNodeInformation", F, 0 },
- { 508, FALSE, ANYINDEX, NILINDEX, NILINDEX, "setNodeEventHandler", F, 0 },
- { 608, FALSE, ANYINDEX, NILINDEX, NILINDEX, "setNodeEventHandler", F, 0 },
- { 708, TRUE , INSTREAMINDEX, NILINDEX, NILINDEX, "getStdin", F, 0 },
- { 808, TRUE , OUTSTREAMINDEX, NILINDEX, NILINDEX, "getStdout", F, 0 },
- { 908, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "getName", F, 0 },
- {2008, TRUE , INSTREAMINDEX, NILINDEX, NILINDEX, "getStdin on node itself", F, 0 },
- {2108, TRUE , OUTSTREAMINDEX, NILINDEX, NILINDEX, "getStdout on node itself", F, 0 },
- {3008, FALSE, ANYINDEX, NILINDEX, NILINDEX, "EMXNextEvent", F, 0 },
- /* None for signature 9 */
- /* Real 10 */
- { 10, TRUE , REALINDEX, REALINDEX, NILINDEX, "+", F, S1 },
- { 110, TRUE , REALINDEX, REALINDEX, NILINDEX, "-", F, S1 },
- { 210, TRUE , REALINDEX, REALINDEX, NILINDEX, "*", F, S1 },
- { 310, TRUE , REALINDEX, REALINDEX, NILINDEX, "/", F, S1 },
- { 410, TRUE , REALINDEX, REALINDEX, NILINDEX, "#", F, S1 },
- { 510, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, ">", F, 0 },
- { 610, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, ">=", F, 0 },
- { 710, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "<", F, 0 },
- { 810, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "<=", F, 0 },
- { 910, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "=", F, 0 },
- {1010, TRUE , BOOLEANINDEX, REALINDEX, NILINDEX, "!=", F, 0 },
- {1110, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- {1210, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "asInteger", F, S },
- {1310, TRUE , REALINDEX, NILINDEX, NILINDEX, "~", T, S },
- /* String 11 */
- { 11, TRUE , CHARACTERINDEX, INTEGERINDEX, NILINDEX, "getElement", F, ARG1 },
- { 111, TRUE , STRINGINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
- { 211, TRUE , STRINGINDEX, STRINGINDEX, NILINDEX, "||", F, 0 },
- { 311, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- { 411, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, ">", F, 0 },
- { 511, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, ">=", F, 0 },
- { 611, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "<", F, 0 },
- { 711, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "<=", F, 0 },
- { 811, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "=", F, 0 },
- { 911, TRUE , BOOLEANINDEX, STRINGINDEX, NILINDEX, "!=", F, 0 },
- {1011, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "length", F, 0 },
- {1111, FALSE, INTEGERINDEX, CHARACTERINDEX, NILINDEX, "lowlevelsleazysetElement", F, 0 },
- /* Vector 12 */
- { 12, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
- { 112, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
- { 212, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
- { 312, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
- { 412, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
- { 512, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
- { 612, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
- { 2012, TRUE , ANYINDEX, INTEGERINDEX, NILINDEX, "getElement", F, 0 },
- { 2112, FALSE, INTEGERINDEX, ANYINDEX, NILINDEX, "setElement", F, 0 },
- { 2212, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "upb", F, 0 },
- { 2312, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "lwb", F, 0 },
- { 2412, TRUE , ANYINDEX, INTEGERINDEX, INTEGERINDEX, "getSlice", F, 0 },
- { 2512, FALSE, INTEGERINDEX, INTEGERINDEX, ANYINDEX, "setSlice", F, 0 },
- { 2612, TRUE , ANYINDEX, ANYINDEX, NILINDEX, "catenate", F, 0 },
- /* Time 13 */
- { 13, TRUE , TIMEINDEX, TIMEINDEX, NILINDEX, "+", F, 0 },
- { 113, TRUE , TIMEINDEX, TIMEINDEX, NILINDEX, "-", F, 0 },
- { 213, TRUE , TIMEINDEX, INTEGERINDEX, NILINDEX, "*", F, 0 },
- { 313, TRUE , TIMEINDEX, INTEGERINDEX, NILINDEX, "/", F, 0 },
- { 413, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, ">", F, 0 },
- { 513, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, ">=", F, 0 },
- { 613, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "<", F, 0 },
- { 713, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "<=", F, 0 },
- { 813, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "=", F, 0 },
- { 913, TRUE , BOOLEANINDEX, TIMEINDEX, NILINDEX, "!=", F, 0 },
- {1013, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "getSeconds", F, 0 },
- {1113, TRUE , INTEGERINDEX, NILINDEX, NILINDEX, "getMicroSeconds", F, 0 },
- {1213, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asString", F, 0 },
- {1313, TRUE , STRINGINDEX, NILINDEX, NILINDEX, "asDate", F, 0 },
- /* none for NodeListElement 14 */
- /* none for NodeList 15 */
- /* InStream 16 */
- { 16, TRUE , INTEGERINDEX, INTEGERINDEX, ANYINDEX, "read", F, 0 },
- { 116, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "close", F, 0 },
- /* OutStream 17 */
- { 17, FALSE, INTEGERINDEX, ANYINDEX, INTEGERINDEX, "write", F, 0 },
- { 117, FALSE, INTEGERINDEX, NILINDEX, NILINDEX, "closeOutStream", F, 0 },
- /* ImmutableVector 18, uses vector ops */
- /* BitChunk 19 */
- { 19, TRUE, INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "getSigned", T, S12 },
- { 119, TRUE, INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "getUnsigned", T, S12 },
- { 219, FALSE, INTEGERINDEX, INTEGERINDEX, INTEGERINDEX, "setSigned", F, 0 },
- { 319, TRUE, INTEGERINDEX, NILINDEX, NILINDEX, "addr", T, S1 },
- /* ownName and ownType */
- { 199, TRUE, STRINGINDEX, NILINDEX, NILINDEX, "ownName", F, 0 },
- { 299, TRUE, SIGNATUREINDEX, NILINDEX, NILINDEX, "ownType", F, 0 },
- /* Dummy at the end */
- { 0, FALSE, NILINDEX, NILINDEX, NILINDEX, NULL, F, 0 }
- };
-
- char *primOpName(typeIndex, opIndex)
- int typeIndex, opIndex;
- {
- int realIndex = typeIndex + opIndex * 100;
- register PrimitiveDesc *p = primitives;
- while (p->number != realIndex && p->number != 0) p++;
- assert(p->number != 0);
- return(p->name);
- }
-
- Variable *forceIntoRegister(v, brand)
- Variable *v;
- Brand brand;
- {
- Variable result;
- if (isAppropriateRegister(v->data, brand)) {
- /* do nothing */
- } else {
- result.data.kind = DD_Address;
- result.data.value.address = nullAddress;
- result.data.value.address.base = Register;
- result.data.value.address.baseIsTemporary = TRUE;
- result.data.value.address.offset = forceAllocateReg(1, brand, 2);
- if (result.data.value.address.offset == -1) {
- implementationBug("Out of temporary registers");
- }
- result.abCon.kind = DD_AbCon;
- setDDAbstractType(result.abCon, getDDAbstractType(v->abCon));
- setDDConcreteType(result.abCon,
- brand == DataBrand ?
- OIDOfBuiltin(B_INSTCT, INTEGERINDEX) :
- OIDOfBuiltin(B_INSTCT, STRINGINDEX));
- ddGenerateAssign(result.data, result.abCon, v->data, v->abCon);
- *v = result;
- }
- return(v);
- }
-
- /*
- * Generate a compare, return whether you had to reverse the sense of the
- * compare.
- */
- DD generateCompare(left, right, size, cond)
- Variable *left, *right;
- char size;
- PSLCondition cond;
- {
- DD result, inter;
- #ifdef sun
- Variable *myleft = right, *myright = left;
- #endif
- #ifdef vax
- Variable *myleft = left, *myright = right;
- #endif
- if (isManifestDD(left->data) && isManifestDD(right->data)) {
- /* figure the result */
- int sign, answer;
- if (left->data.kind == DD_RealManifest) {
- double diff, atof();
- diff = atof(left->data.value.realmanifest) - atof(right->data.value.realmanifest);
- sign = diff == 0.0 ? 0 : diff < 0.0 ? -1 : 1;
- } else {
- int diff = left->data.value.manifest - right->data.value.manifest;
- sign = diff == 0.0 ? 0 : diff < 0.0 ? -1 : 1;
- }
- switch (cond) {
- case NEQ:
- answer = sign != 0;
- break;
- case EQL:
- answer = sign == 0;
- break;
- case GTR:
- answer = sign > 0;
- break;
- case LEQ:
- answer = sign <= 0;
- break;
- case GEQ:
- answer = sign >= 0;
- break;
- case VS:
- answer = FALSE;
- break;
- case VC:
- answer = TRUE;
- break;
- case PL:
- answer = sign >= 0;
- break;
- case MI:
- answer = sign < 0;
- break;
- case ALWAYS:
- answer = TRUE;
- break;
- default:
- assert(FALSE);
- break;
- }
- return(buildManifestDD(answer));
- }
- if (myleft->data.kind == DD_Self) {
- assert(FALSE);
- }
- #ifdef sun
- if (size != 'f') {
- if (isManifestDD(myleft->data) || isRegisterDD(myright->data)) {
- /* we are laughing */
- } else if (isManifestDD(myright->data) || isRegisterDD(myleft->data)) {
- Variable *temp;
- cond = reversedConditions[(int)cond];
- temp = myleft;
- myleft = myright;
- myright = temp;
- } else {
- inter = buildRegisterDD(forceAllocateReg(1, DataBrand, 2));
- emitMove(myright->data, inter, 'l');
- FREEDD(myright->data);
- myright->data = inter;
- }
- }
- #endif
- #ifdef vax
- if (1) {
- #endif
- #ifdef sun
- if (size != 'f') {
- #endif
- emit("\tcmp%c\t", size);
- writeDD(myleft->data, ',');
- writeDD(myright->data, '\n');
- #ifdef sun
- } else {
- if (isAddressRegister(myright->data)) {
- inter = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
- emitMove(myright->data, inter, 'l');
- FREEDD(myright->data);
- myright->data = inter;
- }
- formatAs0r = TRUE;
- emit("\tfmoves\t");
- writeDD(myright->data, ',');
- emit("fp0\n\tf%ss\t", "cmp");
- writeDD(myleft->data, ',');
- emit("fp0\n");
- formatAs0r = FALSE;
- #endif
- }
- result.kind = DD_PSLCondition;
- result.value.condition.psl = cond;
- result.value.condition.isFloat = (size == 'f');
- return(result);
- }
-
- static void checkRange(self, arg1, isString, upb)
- Variable *self, *arg1;
- Boolean isString;
- int upb;
- {
- int okLabel = nextLabelNumber++;
- DD result;
- Variable newself;
-
- newself = *self;
- newself.data = increaseIndirection(newself.data);
- newself.data.value.address.offset = upb;
-
- result = generateCompare(&newself, arg1, 'l', isString ? GTRU : GEQU);
- vPushDD(result, buildConCon(BOOLEANINDEX));
- generateBranch(TRUE, okLabel);
- generateKernelCall("em_assertionFailure");
- emit("L_%d:\n", okLabel);
- }
-
- DD getScratch(brand, depth)
- Brand brand;
- int depth;
- {
- DD s;
- s.kind = DD_Address;
- s.value.address = nullAddress;
- s.value.address.base = Register;
- s.value.address.offset = forceAllocateReg(1, brand, depth);
- if (s.value.address.offset == -1) {
- implementationBug("Out of temporary regs");
- s.value.address.offset = 0;
- }
- s.value.address.baseIsTemporary = TRUE;
- return(s);
- }
-
- void freeScratch(s)
- DD s;
- {
- assert(s.value.address.baseIsTemporary);
- freeReg((unsigned)s.value.address.offset, 1);
- }
-
- void do2OpAdd(result, other, datatype)
- DD result, other;
- char datatype;
- {
- #ifdef sun
- assert(FALSE);
- #endif
- if (other.kind == DD_Manifest && other.value.manifest == 0) {
- /* do nothing */
- } else if (other.kind == DD_RealManifest &&
- atof(other.value.realmanifest) == 0.0) {
- /* do nothing */
- } else if (datatype == 'l' && other.kind == DD_Manifest && other.value.manifest == 1) {
- emit("\tincl\t");
- writeDD(result, '\n');
- } else if (datatype == 'l' && other.kind == DD_Manifest && other.value.manifest == -1) {
- emit("\tdecl\t");
- writeDD(result, '\n');
- } else {
- emit("\tadd%c2\t", datatype);
- writeDD(other, ',');
- writeDD(result, '\n');
- }
- }
-
- PSLCondition compareCs[] = { GTR, GEQ, LSS, LEQ, EQL, NEQ };
- PSLCondition unsignedCompareCs[] = { GTRU, GEQU, LSSU, LEQU, EQL, NEQ };
- char *timeOpNames[] = {
- "plus",
- "minus",
- "times",
- "divide"
- };
-
- /*
- * Take care of Suns strange operands for most instructions. Move one or
- * the other of the operands to the result, return the other one, and make
- * sure that "op other,result" will be legal. I.e., if result is memory,
- * other must be in a register. Note that the abcon must be assigned first
- * if result is on the stack.
- */
-
- void prepareForSunOp(left, right, result, commutative, tOther, tResult)
- Variable *left, *right, *result, **tOther, *tResult;
- Boolean commutative;
- {
- Variable *other;
- Brand brand = abConToBrand(result->abCon);
- DD inter;
- *tResult = *result;
- if (isSameDD(left->data, result->data)) {
- other = right;
- } else if (commutative && isSameDD(right->data, result->data)) {
- other = left;
- } else {
- emitMove(left->data, result->data, 'l');
- other = right;
- if (isPush(result->data)) {
- tResult->data = buildAddressDD(regs_sp, 0);
- }
- }
- if (isMemory(result->data) &&
- !isAppropriateRegister(other->data, brand) &&
- !isManifestDD(other->data)) {
- /* move it to the appropriate register */
- inter = buildRegisterDD(forceAllocateReg(1, brand, 2));
- emitMove(other->data, inter, 'l');
- FREEDD(other->data);
- other->data = inter;
- }
- *tOther = other;
- }
-
- extern Boolean maybeClaimReg();
- extern void moveDataToRegister(), moveVariableToRegisters(), claimReg();
- extern void ddGenerateMovqAssign();
-
- int indexSize;
-
- void doSunRealOp(left, right, op, result)
- DD left, right, result;
- char *op;
- {
- DD nleft, nright;
- nleft = nullDD; nright = nullDD;
- if (isAddressRegister(left)) {
- nleft = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
- emitMove(left, nleft, 'l');
- left = nleft;
- }
- if (isAddressRegister(right)) {
- nright = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
- emitMove(right, nright, 'l');
- right = nright;
- }
- formatAs0r = TRUE;
- emit("\tfmoves\t");
- writeDD(left, ',');
- emit("fp0\n\tf%ss\t", op);
- writeDD(right, ',');
- emit("fp0\n\tfmoves\tfp0,");
- writeDD(result, '\n');
- formatAs0r = FALSE;
- FREEDD(nleft);
- FREEDD(nright);
- }
-
- void generateAMachineLanguagePrimitive(theObject, node, pn, self, nargs,
- isExpression, c)
- NodePtr theObject, node;
- int pn;
- Variable *self;
- int nargs;
- Boolean isExpression;
- Context c;
- {
- register int typeIndex, opIndex;
- int resultRegister, elementTypeSize, stackAddress, tempReg;
- char buffer[32];
- Variable result, *arg1, *arg2, *arg3, *elementv, *other, tResult, temp;
- DD element, scratch, anabcon;
- DD elementAbCon;
- NodePtr ct;
- Symbol elementTypeSymbol;
- Boolean knowResult, abConNeedsAssigning, reversed, needsFreeing;
- PSLCondition cond;
- Brand brand = DataBrand;
- PrimitiveDescPtr pdp;
-
- theNode = node;
- if (nargs == 0) {
- } else if (nargs == 1) {
- arg1 = vPeek(0);
- } else if (nargs == 2) {
- arg1 = vPeek(1);
- arg2 = vPeek(0);
- } else if (nargs == 3) {
- arg1 = vPeek(2);
- arg2 = vPeek(1);
- arg3 = vPeek(0);
- } else assert(FALSE);
- typeIndex = pn % 100;
- opIndex = pn / 100;
- assert(typeIndex == 99 || typeIndex < NUMBUILTINS);
- /*
- * Cheat for now on register allocation.
- */
- for (pdp = primitives; pdp->number != pn && pdp->number != 0; pdp++) ;
- assert(pdp->number == pn);
-
- if (pdp->isFunction) {
- brand = oidToBrand(OIDOfBuiltin(B_INSTAT, pdp->atindex[0]));
- }
- if (c.kind == C_Variable &&
- (!pdp->needsResultReg || isAppropriateRegister(c.v.data, brand))) {
- /*
- * We know the result variable.
- */
- result = c.v;
- knowResult = TRUE;
- /*
- * abConNeedsAssigning = (c.v.abCon.kind == DD_Address);
- * but this tickles a bug in the Sun 3.2 compiler. It generates a tstl
- * instead of a tstb .
- */
- if (c.v.abCon.kind == DD_Address) {
- abConNeedsAssigning = TRUE;
- } else {
- abConNeedsAssigning = FALSE;
- }
- } else if (isExpression) {
- knowResult = FALSE;
- abConNeedsAssigning = FALSE;
- assert(pdp->isFunction);
- /* Try to reuse an existing temporary register as the answer */
- if ((pdp->reuseTemp & ARG2) &&
- (resultRegister = ddHasTempReg(arg2->data, brand)) >= 0) {
- eraseTempIndication(&arg2->data, resultRegister);
- } else if ((pdp->reuseTemp & ARG1) &&
- (resultRegister = ddHasTempReg(arg1->data, brand)) >= 0) {
- eraseTempIndication(&arg1->data, resultRegister);
- } else if ((pdp->reuseTemp & SELF) &&
- (resultRegister = ddHasTempReg(self->data, brand)) >= 0) {
- eraseTempIndication(&self->data, resultRegister);
- } else if (pdp->needsResultReg) {
- resultRegister = forceAllocateReg(1, brand, nargs);
- } else {
- resultRegister = allocateReg(1, brand);
- }
- if (resultRegister != -1) {
- result.data.kind = DD_Address;
- result.data.value.address = nullAddress;
- result.data.value.address.base = Register;
- result.data.value.address.offset = resultRegister;
- result.data.value.address.baseIsTemporary = TRUE;
- result.abCon = buildConCon(INTEGERINDEX);
- } else {
- stackAddress = TS_Allocate(4, brand);
- result.data.kind = DD_Address;
- result.data.value.address = nullAddress;
- result.data.value.address.base = regs_l;
- result.data.value.address.baseIsTemporary = TRUE;
- result.data.value.address.offset = stackAddress;
- result.abCon = buildConCon(INTEGERINDEX);
- }
- } else {
- result.data = nullDD;
- result.abCon = nullDD;
- knowResult = FALSE;
- abConNeedsAssigning = FALSE;
- }
-
- /*
- * The abcon needs to be assigned first, since it might be -(sp).
- */
- #define SETRESULTABCON(S) if (!knowResult) result.abCon = (S); \
- else if (abConNeedsAssigning) emitMove((S), result.abCon, 'l');
-
- TRACE2(primitive, 1, "Primitive %s of type %s",
- primOpName(typeIndex, opIndex), builtinTypeNames[typeIndex]);
- switch (typeIndex) {
- case ABSTRACTTYPEINDEX:
- assert(FALSE);
- break;
- case ANYINDEX:
- assert(FALSE);
- break;
- case ARRAYINDEX:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- case BOOLEANINDEX:
- anabcon = buildConCon(BOOLEANINDEX);
- switch (opIndex) {
- case 0: /* > */
- case 1: /* >= */
- case 2: /* < */
- case 3: /* <= */
- case 4: /* = */
- case 5: /* != */
- FREEV(&result);
- result.abCon = anabcon;
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- result.data = generateCompare(self, arg1, 'l', unsignedCompareCs[opIndex]);
- break;
- case 6: /* & */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\textzv\t$0,");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
- emit("\tandl\t");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 7: /* | */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\tbisl3\t");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
- emit("\torl\t");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 8: /* ! */
- if (self->data.kind == DD_PSLCondition) {
- FREEV(&result);
- result.data = self->data;
- result.abCon = self->abCon;
- result.data.value.condition.psl =
- negatedConditions[(int)result.data.value.condition.psl];
- } else {
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- if (c.kind == C_Variable) {
- temp.data = buildManifestDD(1);
- temp.abCon = buildConCon(INTEGERINDEX);
- #ifdef vax
- emit("\tsubl3\t");
- writeDD(self->data, ',');
- writeDD(temp.data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, &temp, &result, FALSE, &other, &tResult);
- emit("\tsubl\t");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- } else if (c.kind == C_PSL || c.kind == C_Any) {
- emit("\ttstl\t");
- writeDD(self->data, '\n');
- FREEV(&result);
- result.data.kind = DD_PSLCondition;
- result.data.value.condition.psl = EQL;
- result.data.value.condition.isFloat = FALSE;
- result.abCon = anabcon;
- } else {
- assert(FALSE);
- }
- }
- break;
- case 9: /* asString */
- FREEV(&result);
- moveDataToRegister(self, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("emboolean_asString");
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case CHARACTERINDEX:
- anabcon = buildConCon(CHARACTERINDEX);
- switch (opIndex) {
- case 0: /* > */
- case 1: /* >= */
- case 2: /* < */
- case 3: /* <= */
- case 4: /* = */
- case 5: /* != */
- FREEV(&result);
- result.abCon = buildConCon(BOOLEANINDEX);
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- result.data = generateCompare(self, arg1, 'l', unsignedCompareCs[opIndex]);
- break;
- case 6: /* asString */
- FREEV(&result);
- moveDataToRegister(self, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("emcharacter_asString");
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- case 7: /* ord */
- FREEV(&result);
- result.data = self->data;
- result.abCon = buildConCon(INTEGERINDEX);
- DISCARDDD(self->data);
- break;
- case 8: /* Character.literal */
- FREEV(&result);
- FREEV(self);
- result.data = arg1->data;
- result.abCon = buildConCon(CHARACTERINDEX);
- DISCARDDD(arg1->data);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case CONDITIONINDEX:
- switch (opIndex) {
- case 0: /* Create */
- FREEV(&result);
- result.data.kind = DD_Manifest;
- result.data.value.manifest = 0;
- result.abCon = buildConCon(CONDITIONINDEX);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case INTEGERINDEX:
- anabcon = buildConCon(INTEGERINDEX);
- switch (opIndex) {
- case 0: /* + */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- #ifdef vax
- if (isSameDD(self->data, result.data)) {
- do2OpAdd(self->data, arg1->data, 'l');
- self->data = nullDD;
- } else if (isSameDD(arg1->data, result.data)) {
- do2OpAdd(arg1->data, self->data, 'l');
- arg1->data = nullDD;
- } else {
- emit("\taddl3\t");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- }
- #endif
- #ifdef sun
- prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
- emit("\tadd%sl\t",
- other->data.kind == DD_Manifest && inRange(other->data.value.manifest, 1, 8) ? "q" : "");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 1: /* - */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == 0) {
- FREEDD(result.data);
- result.data = self->data;
- self->data = nullDD;
- #ifdef vax
- } else if (isSameDD(self->data, result.data)) {
- if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == 1) {
- emit("\tdecl\t");
- writeDD(self->data, '\n');
- } else if (arg1->data.kind == DD_Manifest && arg1->data.value.manifest == -1) {
- emit("\tincl\t");
- writeDD(self->data, '\n');
- } else {
- emit("\tsubl2\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, '\n');
- }
- } else {
- emit("\tsubl3\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- } else {
- prepareForSunOp(self, arg1, &result, FALSE, &other, &tResult);
- emit("\tsub%sl\t",
- other->data.kind == DD_Manifest && inRange(other->data.value.manifest, 1, 8) ? "q" : "");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
-
- }
- break;
- case 2: /* * */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- #ifdef sun
- assert(isDataRegister(result.data));
- #endif
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\tmull3\t");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, arg1, &result, TRUE, &other, &tResult);
- emit("\tmulsl\t");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 3: /* / */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- #ifdef sun
- assert(isDataRegister(result.data));
- #endif
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\tdivl3\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, arg1, &result, FALSE, &other, &tResult);
- emit("\tdivsl\t");
- writeDD(other->data, ',');
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 4: /* # */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- #ifdef sun
- assert(isDataRegister(result.data));
- #endif
- SETRESULTABCON(anabcon);
- #ifdef vax
- scratch = getScratch(DataBrand, 2);
- emit("\tdivl3\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, ',');
- writeDD(scratch, '\n');
- emit("\tmull2\t");
- writeDD(arg1->data, ',');
- writeDD(scratch, '\n');
- emit("\tsubl3\t");
- writeDD(scratch, ',');
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- freeScratch(scratch);
- #endif
- #ifdef sun
- needsFreeing = FALSE;
- tempReg = ddHasTempReg(arg1->data, DataBrand);
- if (tempReg < 0) {
- tempReg = forceAllocateReg(1, DataBrand, 2);
- needsFreeing = TRUE;
- }
- temp.data = buildRegisterDD(tempReg);
- temp.abCon = buildConCon(INTEGERINDEX);
- prepareForSunOp(self, arg1, &temp, FALSE, &other, &tResult);
- emit("\tdivsll\t");
- writeDD(other->data, ',');
- writeDD(result.data, ':');
- writeDD(temp.data, '\n');
- if (needsFreeing) FREEV(&temp);
- #endif
- break;
- case 5: /* > */
- case 6: /* >= */
- case 7: /* < */
- case 8: /* <= */
- case 9: /* = */
- case 10: /* != */
- FREEV(&result);
- result.abCon = buildConCon(BOOLEANINDEX);
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- result.data = generateCompare(self, arg1, 'l', compareCs[opIndex - 5]);
- break;
- case 11: /* asString */
- FREEV(&result);
- moveDataToRegister(self, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("eminteger_asString");
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- case 12: /* ~ */
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\tmnegl\t");
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- prepareForSunOp(self, self, &result, FALSE, &other, &tResult);
- emit("\tnegl\t");
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 13: /* asReal */
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(REALINDEX));
- #ifdef vax
- emit("\tcvtlf\t");
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- if (isAddressRegister(self->data)) {
- tempReg = forceAllocateReg(1, DataBrand, 1);
- temp.data = buildRegisterDD(tempReg);
- emitMove(self->data, temp.data, 'l');
- FREEDD(self->data);
- self->data = temp.data;
- }
- emit("\tfmovel\t");
- writeDD(self->data, ',');
- emit("fp0\n\tfmoves\tfp0,");
- writeDD(result.data, '\n');
- #endif
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case NILINDEX:
- assert(FALSE);
- break;
- case NODEINDEX:
- switch (opIndex) {
- case 0: /* delay */
- moveDataToRegister(arg1, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_delay");
- break;
- case 1: /* waitUntil */
- moveDataToRegister(arg1, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_waitUntil");
- break;
- case 2: /* getActiveNodes */
- case 3: /* getAllNodes */
- preemptReg(regs_scratch, 4);
- if (opIndex == 2) generateKernelCall("em_getActiveNodes");
- else generateKernelCall("em_getAllNodes");
- claimReg(regs_arg1, 2, VariableBrand);
- FREEV(&result);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = nextAddress(result.data);
- setDDAbstractType(result.abCon, OIDOfBuiltin(B_INSTAT, NODELISTINDEX));
- break;
- case 4: /* getNodeInformation */
- moveDataToRegister(arg1, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_getNodeInformation");
- FREEV(arg1);
- claimReg(regs_arg1, 2, VariableBrand);
- FREEV(&result);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = nextAddress(result.data);
- setDDAbstractType(result.abCon, OIDOfBuiltin(B_INSTAT, NODELISTELEMENTINDEX));
- break;
- case 5: /* setNodeEventHandler */
- case 6: /* removeNodeEventHandler */
- moveVariableToRegisters(arg1, regs_arg1);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- if (opIndex == 5) generateKernelCall("em_setNodeEventHandler");
- else generateKernelCall("em_removeNodeEventHandler");
- break;
- case 7: /* getStdin */
- case 8: /* getStdout */
- case 9: /* getName */
- case 20: /* getStdin on NODE */
- case 21: /* getStdout on NODE */
- FREEV(&result);
- preemptReg(regs_scratch, 4);
- if (opIndex == 7) generateKernelCall("em_getStdIn");
- else if (opIndex == 8) generateKernelCall("em_getStdOut");
- else if (opIndex == 9) generateKernelCall("em_getName");
- else if (opIndex == 20) generateKernelCall("em_getMyStdIn");
- else if (opIndex == 21) generateKernelCall("em_getMyStdOut");
- else assert(FALSE);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- if (opIndex == 7 || opIndex == 20) {
- result.abCon = buildConCon(INSTREAMINDEX);
- } else if (opIndex == 8) {
- result.abCon = buildConCon(STRINGINDEX);
- } else {
- result.abCon = buildConCon(OUTSTREAMINDEX);
- }
- break;
- case 30:
- moveDataToRegister(arg1, regs_arg1);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("emx_nextevent");
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case SIGNATUREINDEX:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- case REALINDEX:
- anabcon = buildConCon(REALINDEX);
- switch (opIndex) {
- case 0: /* + */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(REALINDEX));
- #ifdef vax
- if (isSameDD(self->data, result.data)) {
- do2OpAdd(self->data, arg1->data, 'f');
- self->data = nullDD;
- } else if (isSameDD(arg1->data, result.data)) {
- do2OpAdd(arg1->data, self->data, 'f');
- arg1->data = nullDD;
- } else {
- emit("\taddf3\t");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- }
- #endif
- #ifdef sun
- doSunRealOp(self->data, arg1->data, "add", result.data);
- #endif
- break;
- case 1: /* - */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(REALINDEX));
- #ifdef vax
- if (arg1->data.kind == DD_RealManifest &&
- atof(arg1->data.value.realmanifest) == 0.0) {
- FREEDD(result.data);
- result.data = self->data;
- self->data = nullDD;
- } else if (isSameDD(self->data, result.data)) {
- emit("\tsubf2\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, '\n');
- } else {
- emit("\tsubf3\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- }
- #endif
- #ifdef sun
- doSunRealOp(self->data, arg1->data, "sub", result.data);
- #endif
- break;
- case 2: /* * */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(REALINDEX));
- #ifdef vax
- if (isSameDD(self->data, result.data)) {
- emit("\tmulf2\t");
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- } else if (isSameDD(arg1->data, result.data)) {
- emit("\tmulf2\t");
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- } else {
- emit("\tmulf3\t");
- writeDD(self->data, ',');
- writeDD(arg1->data, ',');
- writeDD(result.data, '\n');
- }
- #endif
- #ifdef sun
- doSunRealOp(self->data, arg1->data, "mul", result.data);
- #endif
- break;
- case 3: /* / */
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(REALINDEX));
- #ifdef vax
- if (isSameDD(self->data, result.data)) {
- emit("\tdivf2\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, '\n');
- } else {
- emit("\tdivf3\t");
- writeDD(arg1->data, ',');
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- }
- #endif
- #ifdef sun
- doSunRealOp(self->data, arg1->data, "div", result.data);
- #endif
- break;
- case 4: /* # */
- FREEV(&result);
- result.data = nilDD;
- result.abCon = nilDD;
- generateKernelCall("em_assertionFailure");
- break;
- case 5: /* > */
- case 6: /* >= */
- case 7: /* < */
- case 8: /* <= */
- case 9: /* = */
- case 10: /* != */
- FREEV(&result);
- result.abCon = buildConCon(BOOLEANINDEX);
- vForceToTemp(arg1, TS_All);
- vForceToTemp(self, TS_All);
- result.data = generateCompare(self, arg1, 'f', compareCs[opIndex - 5]);
- break;
- case 11: /* asString */
- FREEV(&result);
- moveDataToRegister(self, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("emreal_asString");
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- case 12: /* asInteger */
- vForceToTemp(self, TS_All);
- SETRESULTABCON(buildConCon(INTEGERINDEX));
- #ifdef vax
- emit("\tcvtrfl\t");
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- if (isAddressRegister(self->data)) {
- temp.data = buildRegisterDD(forceAllocateReg(1, DataBrand, 1));
- emitMove(self->data, temp.data, 'l');
- FREEDD(self->data);
- self->data = temp.data;
- }
- emit("\tfintrzs\t");
- writeDD(self->data, ',');
- emit("fp0\n\tfmovel\tfp0,");
- writeDD(result.data, '\n');
- #endif
- break;
- case 13: /* ~ */
- vForceToTemp(self, TS_All);
- SETRESULTABCON(anabcon);
- #ifdef vax
- emit("\tmnegf\t");
- writeDD(self->data, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- assert(isDataRegister(result.data));
- emitMove(self->data, result.data, 'l');
- emit("\tbchg\t");
- writeDD(buildManifestDD(31), ',');
- writeDD(result.data, '\n');
- #endif
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case STRINGINDEX:
- switch (opIndex) {
- case 0: /* getElement */
- self = forceIntoRegister(self, ODPBrand);
- arg1 = forceIntoRegister(arg1, DataBrand);
- SETRESULTABCON(buildConCon(CHARACTERINDEX));
- checkRange(self, arg1, TRUE, String_sizeInBytes);
- #ifdef vax
- emit("\tmovzbl\t%d(%s)[%s],", String_data,
- RN(self->data.value.address.offset), RN(arg1->data.value.address.offset));
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- temp.data = buildManifestDD(0);
- temp.abCon = buildConCon(INTEGERINDEX);
- prepareForSunOp(&temp, &temp, &result, FALSE, &other, &tResult);
- if (isMemory(tResult.data)) {
- tResult.data.value.address.offset += 3;
- }
- emit("\tmovb\t");
- emit("%s@(%d,%s:l),", RN(self->data.value.address.offset), String_data,
- RN(arg1->data.value.address.offset));
- writeDD(tResult.data, '\n');
- #endif
- break;
- case 11: /* lowlevelsleazysetElement */
- self = forceIntoRegister(self, ODPBrand);
- arg1 = forceIntoRegister(arg1, DataBrand);
- /* checkRange(self, arg1, TRUE, String_sizeInBytes); */
- #ifdef vax
- emit("\tcvtlb\t");
- writeDD(arg2->data, ',');
- emit("%d(%s)[%s]\n", String_data,
- RN(self->data.value.address.offset),
- RN(arg1->data.value.address.offset));
- #endif
- #ifdef sun
- if (isMemory(arg2->data)) vForceToTemp(arg2, TS_Stack);
- if (isMemory(arg2->data)) {
- arg2->data.value.address.offset += 3;
- }
- emit("\tmovb\t");
- writeDD(arg2->data, ',');
- emit("%s@(%d,%s:l)\n", RN(self->data.value.address.offset),
- String_data,
- RN(arg1->data.value.address.offset));
- #endif
- break;
- case 1: /* getSlice */
- FREEV(&result);
- moveDataToRegister(arg2, regs_arg3, DataBrand);
- moveDataToRegister(arg1, regs_arg2, DataBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
-
- preemptReg(regs_scratch, 1);
-
- generateKernelCall("ems_getSlice");
- FREEV(arg2);
- FREEV(arg1);
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- case 2: /* || */
- FREEV(&result);
- moveDataToRegister(arg1, regs_arg2, ODPBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
-
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
-
- generateKernelCall("ems_catenate");
- FREEV(arg1);
- FREEV(self);
-
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- break;
- case 3: /* asString */
- FREEV(&result);
- result.data = self->data;
- result.abCon = self->abCon;
- break;
- case 4: /* > */
- case 5: /* >= */
- case 6: /* < */
- case 7: /* <= */
- case 8: /* = */
- case 9: /* != */
- #ifdef vax
- FREEV(&result);
- arg1 = forceIntoRegister(arg1, ODPBrand);
- self = forceIntoRegister(self, ODPBrand);
-
- emit("\tcmpc5\t%d(%s), %d(%s), $0, ",
- String_sizeInBytes, RN(self->data.value.address.offset),
- String_data, RN(self->data.value.address.offset));
- emit("%d(%s), %d(%s)\n",
- String_sizeInBytes, RN(arg1->data.value.address.offset),
- String_data, RN(arg1->data.value.address.offset));
- FREEV(self);
- FREEV(arg1);
- result.data.kind = DD_PSLCondition;
- result.data.value.condition.psl = unsignedCompareCs[opIndex - 4];
- result.data.value.condition.isFloat = FALSE;
- result.abCon = buildConCon(BOOLEANINDEX);
- #endif
- #ifdef sun
- FREEV(&result);
- moveDataToRegister(arg1, regs_arg2, ODPBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- generateKernelCall("ems_compare");
- FREEV(arg1);
- FREEV(self);
- result.data.kind = DD_PSLCondition;
- result.data.value.condition.psl = unsignedCompareCs[opIndex - 4];
- result.data.value.condition.isFloat = FALSE;
- result.abCon = buildConCon(BOOLEANINDEX);
- #endif
- break;
- case 10: /* length */
- FREEV(&result);
- result = *forceIntoRegister(self, ODPBrand);
- DISCARDV(self);
- result.abCon = buildConCon(INTEGERINDEX);
- result.data = increaseIndirection(result.data);
- result.data.value.address.offset = String_sizeInBytes;
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case VECTORINDEX:
- /*
- * Vectors need to know if they are holding 32 bit data pointers with
- * known abcons or 64 bit data pointer/abcon pairs. This is found by
- * the following stuff:
- * 1. Look at the abcon for self. fetch the concrete oblit.
- * 2. Find the getelement operation, and fetch its result symbol
- * 3. Look at its types.
- * This process implies that when we do vector.of[X], we need to change
- * X depending on the know concrete type status of the setelement
- * calls. For the moment, lets just worry about the builtin guys.
- */
- assert (self->abCon.kind != DD_AbCon ||
- getConcreteTypeFromAbCon(self->abCon) == theObject);
- ct = theObject;
- elementTypeSymbol = getElementTypeSymbol(ct);
- elementTypeSize = getSymbolSize(elementTypeSymbol);
- switch (opIndex) {
- case 0: /* getElement */
- arg1 = forceIntoRegister(arg1, DataBrand);
- elementv = forceIntoRegister(self, ODPBrand);
- element = elementv->data;
- if (! knowResult) {
- if (elementTypeSize <= 4) {
- FREEV(&result);
- result.abCon = vGetSymbolAbCon(elementTypeSymbol, nullDD);
- assert(result.abCon.kind == DD_AbCon);
- brand = oidToBrand(getDDAbstractType(result.abCon));
- resultRegister = allocateReg(1, brand);
- if (resultRegister != -1) {
- result.data.kind = DD_Address;
- result.data.value.address = nullAddress;
- result.data.value.address.base = Register;
- result.data.value.address.offset = resultRegister;
- result.data.value.address.baseIsTemporary = TRUE;
- } else {
- stackAddress = TS_Allocate(4, brand);
- result.data.kind = DD_Address;
- result.data.value.address = nullAddress;
- result.data.value.address.base = regs_l;
- result.data.value.address.baseIsTemporary = TRUE;
- result.data.value.address.offset = stackAddress;
- }
- } else {
- assert(elementTypeSize == 8);
- FREEV(&result);
- stackAddress = TS_Allocate(8, VariableBrand);
- result.data.value.address.base = regs_l;
- result.data.value.address.baseIsTemporary = TRUE;
- result.data.value.address.offset = stackAddress;
- result.abCon = nextAddress(result.data);
- result.abCon.value.address.baseIsTemporary = TRUE;
- setDDAbstractType(result.abCon, getDDAbstractType(c.v.abCon));
- }
- }
- checkRange(elementv, arg1, FALSE,
- (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4);
- element = increaseIndirection(element);
- element.value.address.offset =
- ct->b.oblit.f.immutable ? IMVector_data : Vector_data;
- element.value.address.hasIndex = TRUE;
- element.value.address.indexReg = arg1->data.value.address.offset;
- elementAbCon = vGetSymbolAbCon(elementTypeSymbol, element);
- indexSize = elementTypeSize;
- if (elementTypeSize == 1) {
- #ifdef vax
- emit("\tmovzbl\t");
- writeDD(element, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- temp.data = buildManifestDD(0);
- temp.abCon = buildConCon(INTEGERINDEX);
- prepareForSunOp(&temp, &temp, &result, FALSE, &other, &tResult);
- if (isMemory(tResult.data)) {
- tResult.data.value.address.offset += 3;
- }
- emitMove(element, tResult.data, 'b');
- #endif
- FREEDD(element);
- FREEDD(elementAbCon);
- } else {
- ddGenerateAssign(result.data, result.abCon, element, elementAbCon);
- }
- FREEV(arg1);
- assert(self == elementv);
- DISCARDV(self);
- if (elementTypeSize == 8) {
- if (result.data.kind == DD_Address &&
- result.data.value.address.autoDecrement) {
- /* we are pushing this on the stack */
- assert(result.abCon.kind == DD_Address);
- assert(result.abCon.value.address.autoDecrement);
- /* no need to fix the Ab/Con = what we stored will be fine */
- } else {
- fixDDView(result.abCon, result.abCon,
- getDDAbstractType(result.abCon), FALSE);
- }
- }
- break;
- case 1: /* setElement */
- if (arg2->data.kind == DD_Address && arg2->data.value.address.autoIncrement &&
- (arg1->data.kind == DD_Address && arg1->data.value.address.autoIncrement ||
- self->data.kind == DD_Address && self->data.value.address.autoIncrement)) {
- implementationBug("Can't do set elements of hairy expressions.");
- return;
- }
- self = forceIntoRegister(self, ODPBrand);
- element = self->data;
- arg1 = forceIntoRegister(arg1, DataBrand);
- checkRange(self, arg1, FALSE,
- (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4);
- element = increaseIndirection(element);
- element.value.address.offset =
- ct->b.oblit.f.immutable ? IMVector_data : Vector_data;
- element.value.address.hasIndex = TRUE;
- element.value.address.indexReg = arg1->data.value.address.offset;
- elementAbCon = vGetSymbolAbCon(elementTypeSymbol, element);
- setDDAbstractType(elementAbCon, getDDAbstractType(arg2->abCon));
- indexSize = elementTypeSize;
- if (elementTypeSize == 1) {
- #ifdef sun
- temp = *arg2;
- if (isMemory(temp.data)) {
- temp.data.value.address.offset += 3;
- }
- emitMove(temp.data, element, 'b');
- #endif
- #ifdef vax
- emit("\tcvtlb\t");
- writeDD(arg2->data, ',');
- writeDD(element, '\n');
- #endif
- } else {
- if (arg2->data.kind == DD_Address &&
- arg2->data.value.address.autoIncrement &&
- arg2->abCon.kind == DD_Address &&
- arg2->abCon.value.address.autoIncrement) {
- /* panic. we need to fix the ab-con, but cannot do it now. */
- OID realOID;
- realOID = getDDAbstractType(elementAbCon);
- setDDAbstractType(elementAbCon, (OID) 0);
- ddGenerateMovqAssign(elementTypeSize, element, elementAbCon,
- arg2->data, arg2->abCon);
- DISCARDV(arg2);
- setDDAbstractType(elementAbCon, realOID);
- } else {
- ddGenerateMovqAssign(elementTypeSize, element, elementAbCon,
- arg2->data, arg2->abCon);
- DISCARDV(arg2);
- }
- }
- break;
- case 2: /* upb */
- self = forceIntoRegister(self, ODPBrand);
- self->data = increaseIndirection(self->data);
- self->data.value.address.offset =
- (ct->b.oblit.f.immutable ? IMVector_sizeInBytes : Vector_sizeInBytes) - 4;
- SETRESULTABCON(buildConCon(INTEGERINDEX));
- emitMove(self->data, result.data, 'l');
- break;
- case 3: /* lwb */
- FREEV(&result);
- result.data.kind = DD_Manifest;
- result.data.value.manifest = 0;
- result.abCon = buildConCon(INTEGERINDEX);
- break;
- case 4: /* getSlice */
- FREEV(&result);
- assert(self->abCon.kind == DD_AbCon);
- result.abCon = self->abCon;
- moveDataToRegister(arg2, regs_arg3, DataBrand);
- moveDataToRegister(arg1, regs_arg2, DataBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- if (elementTypeSize == 1) {
- generateKernelCall("emvector_get1Slice");
- } else if (elementTypeSize == 4) {
- generateKernelCall("emvector_get4Slice");
- } else {
- assert(elementTypeSize == 8);
- generateKernelCall("emvector_get8Slice");
- }
- FREEV(arg2);
- FREEV(arg1);
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- break;
- case 5: /* setSlice */
- FREEV(&result);
- moveDataToRegister(arg3, regs_scratch, ODPBrand);
- moveDataToRegister(arg2, regs_arg3, DataBrand);
- moveDataToRegister(arg1, regs_arg2, DataBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
- if (elementTypeSize == 1) {
- generateKernelCall("emvector_set1Slice");
- } else if (elementTypeSize == 4) {
- generateKernelCall("emvector_set4Slice");
- } else {
- assert(elementTypeSize == 8);
- generateKernelCall("emvector_set8Slice");
- }
- FREEV(arg3);
- FREEV(arg2);
- FREEV(arg1);
- FREEV(self);
- break;
- case 6: /* catenate */
- FREEV(&result);
- assert(self->abCon.kind == DD_AbCon);
- result.abCon = self->abCon;
- moveDataToRegister(arg1, regs_arg2, ODPBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
-
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
-
- if (elementTypeSize == 1) {
- generateKernelCall("emvector_catenate1");
- } else if (elementTypeSize == 4) {
- generateKernelCall("emvector_catenate4");
- } else {
- assert(elementTypeSize == 8);
- generateKernelCall("emvector_catenate8");
- }
- FREEV(arg1);
- FREEV(self);
-
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- }
- break;
- case TIMEINDEX:
- anabcon = buildConCon(TIMEINDEX);
- if (opIndex < 0) {
- unimplementedPrimitive(opIndex, typeIndex);
- } else if (opIndex <= 9) {
- FREEV(&result);
- result.abCon = buildConCon(TIMEINDEX);
- moveDataToRegister(arg1, regs_arg2, ODPBrand);
- moveDataToRegister(self, regs_arg1, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- FREEV(self);
- if (opIndex <= 3) {
- sprintf(buffer, "emtime_%s", timeOpNames[opIndex]);
- generateKernelCall(buffer);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- } else {
- generateKernelCall("emtime_compare");
- result.data.kind = DD_PSLCondition;
- result.abCon = buildConCon(BOOLEANINDEX);
- result.data.value.condition.psl = compareCs[opIndex-4];
- result.data.value.condition.isFloat = FALSE;
- }
- } else if (opIndex <= 11) {
- FREEV(&result);
- result = *forceIntoRegister(self, ODPBrand);
- DISCARDV(self);
- result.abCon = buildConCon(INTEGERINDEX);
- result.data = increaseIndirection(result.data);
- result.data.value.address.offset = ROData_inlineData;
- if (opIndex == 11) result.data.value.address.offset += 4;
- } else if (opIndex <= 13) {
- FREEV(&result);
- moveDataToRegister(self, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- if (opIndex == 12) generateKernelCall("emtime_asString");
- else generateKernelCall("emtime_asDate");
- FREEV(self);
- claimReg(regs_arg1, 1, ODPBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(STRINGINDEX);
- } else {
- unimplementedPrimitive(opIndex, typeIndex);
- }
- break;
- case INSTREAMINDEX:
- switch (opIndex) {
- case 0: /* em_read */
- moveDataToRegister(arg1, regs_arg1, DataBrand);
- moveDataToRegister(arg2, regs_arg2, ODPBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg3, 1);
- generateKernelCall("em_read");
- FREEV(arg1);
- FREEV(arg2);
- claimReg(regs_arg1, 1, DataBrand);
- result.data = buildRegisterDD(regs_arg1);
- result.abCon = buildConCon(INTEGERINDEX);
- break;
- case 1: /* em_closeInStream */
- moveDataToRegister(arg1, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_closeInStream");
- FREEV(arg1);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case OUTSTREAMINDEX:
- switch (opIndex) {
- case 0: /* em_write */
- moveDataToRegister(arg1, regs_arg1, DataBrand);
- moveDataToRegister(arg2, regs_arg2, ODPBrand);
- moveDataToRegister(arg3, regs_arg3, DataBrand);
- preemptReg(regs_scratch, 1);
- generateKernelCall("em_write");
- FREEV(arg1);
- FREEV(arg2);
- FREEV(arg3);
- break;
- case 1: /* em_closeOutStream */
- moveDataToRegister(arg1, regs_arg1, DataBrand);
- preemptReg(regs_scratch, 1);
- preemptReg(regs_arg2, 2);
- generateKernelCall("em_closeOutStream");
- FREEV(arg1);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case BITCHUNKINDEX:
- switch (opIndex) {
- case 0: /* getSigned */
- case 1: /* getUnsigned */
- #ifdef vax
- self = forceIntoRegister(self, ODPBrand);
- emit("\text%sv\t", opIndex == 1 ? "z" : "");
- writeDD(arg1->data, ',');
- writeDD(arg2->data, ',');
- scratch = increaseIndirection(self->data);
- scratch.value.address.offset = Vector_data;
- writeDD(scratch, ',');
- writeDD(result.data, '\n');
- #endif
- #ifdef sun
- /* we know that the result is a data register, if arg1 is not in a
- * register, then put it in result. */
- {
- int byteoffset = Vector_data, offset;
- if (isManifestDD(arg1->data)) {
- assert (arg1->data.kind == DD_Manifest);
- offset = arg1->data.value.manifest;
- byteoffset += ((offset / 32) * 4);
- arg1->data.value.manifest = offset % 32;
- } else {
- if (!isDataRegister(arg1->data)) {
- emitMove(arg1->data, result.data, 'l');
- arg1->data = result.data;
- eraseTempIndication(&arg1->data, result.data.value.address.offset);
- }
- }
- if (!isManifestDD(arg2->data)) {
- arg2 = forceIntoRegister(arg2, DataBrand);
- }
- self = forceIntoRegister(self, ODPBrand);
- scratch = increaseIndirection(self->data);
- scratch.value.address.offset = byteoffset;
- emit("\tbfext%s\t", opIndex == 1 ? "u" : "s");
- writeDD(scratch, '{');
- writeDD(arg1->data, ':');
- writeDD(arg2->data, '}');
- emit(",");
- writeDD(result.data, '\n');
- }
- #endif
- break;
- case 2: /* setSigned */
- #ifdef vax
- self = forceIntoRegister(self, ODPBrand);
- emit("\tinsv\t");
- writeDD(arg3->data, ',');
- writeDD(arg1->data, ',');
- writeDD(arg2->data, ',');
- scratch = increaseIndirection(self->data);
- scratch.value.address.offset = String_data;
- writeDD(scratch, '\n');
- #endif
- #ifdef sun
- {
- int byteoffset = Vector_data, offset, nManifest = 0;
- if (isManifestDD(arg1->data)) {
- nManifest++;
- assert (arg1->data.kind == DD_Manifest);
- offset = arg1->data.value.manifest;
- byteoffset += ((offset / 32) * 4);
- arg1->data.value.manifest = offset % 32;
- } else if (!isDataRegister(arg1->data)) {
- arg1 = forceIntoRegister(arg1, DataBrand);
- }
- if (isManifestDD(arg2->data)) {
- nManifest++;
- } else {
- arg2 = forceIntoRegister(arg2, DataBrand);
- }
- if (nManifest == 0) {
- /* we need to find another data register, steal d2 */
- emit("\tmovl\td2,sp@-\n");
- element = buildRegisterDD(6 /* d2 */);
- emitMove(arg3->data, element, 'l');
- } else {
- arg3 = forceIntoRegister(arg3, DataBrand);
- element = arg3->data;
- }
- self = forceIntoRegister(self, ODPBrand);
- emit("\tbfins\t");
- writeDD(element, ',');
- scratch = increaseIndirection(self->data);
- scratch.value.address.offset = byteoffset;
- writeDD(scratch, '{');
- writeDD(arg1->data, ':');
- writeDD(arg2->data, '}');
- emit("\n");
- if (nManifest == 0) {
- emit("\tmovl\tsp@+,d2\n");
- }
- }
- #endif
- break;
- case 3: /* addr */
- emitMove(self->data, result.data, 'l');
- #ifdef sun
- emit("\taddl\t");
- #endif
- #ifdef vax
- emit("\taddl2\t");
- #endif
- writeDD(buildManifestDD(Vector_data), ',');
- writeDD(result.data, '\n');
- break;
-
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- case 99:
- if (self->data.value.address.autoIncrement &&
- self->data.value.address.base == Stack &&
- self->data.value.address.offset == 0 &&
- self->abCon.value.address.autoIncrement &&
- self->abCon.value.address.base == Stack &&
- self->abCon.value.address.offset == 0) {
- /* This is a result, that must be freed, since we ignore it */
- #ifdef vax
- emit("\taddl2\t$8,sp\n");
- #endif
- #ifdef sun
- emit("\taddqw\t#8,sp\n");
- #endif
- }
- switch (opIndex) {
- case 1: /* ownName */
- FREEV(&result);
- assert (self->abCon.kind != DD_AbCon ||
- getConcreteTypeFromAbCon(self->abCon) == theObject);
- vPushOwnName(theObject);
- result = vPop();
- FREEV(self);
- break;
- case 2: /* ownType */
- FREEV(&result);
- assert (self->abCon.kind != DD_AbCon ||
- getConcreteTypeFromAbCon(self->abCon) == theObject);
- vPushOwnType(theObject);
- result = vPop();
- FREEV(self);
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- break;
- default:
- unimplementedPrimitive(opIndex, typeIndex);
- break;
- }
- FREEV(self);
-
- if (nargs == 0) {
- } else if (nargs == 1) {
- vDiscard();
- } else if (nargs == 2) {
- vDiscard();
- vDiscard();
- } else if (nargs == 3) {
- vDiscard();
- vDiscard();
- vDiscard();
- } else assert(FALSE);
- if (isExpression) vPush(result);
- TRACE2(primitive, 1, "End of primitive %s of type %s",
- primOpName(typeIndex, opIndex), builtinTypeNames[typeIndex]);
- }
-
- /*ARGSUSED*/
- void generateACPrimitive(name, nargs, isExpression, c)
- char *name;
- int nargs;
- Boolean isExpression;
- Context c;
- {
- int resultRegister, i;
- Variable result;
- Variable *arg;
- DD mypusher;
- resultRegister = regs_arg1;
- result.abCon = buildConCon(INTEGERINDEX);
-
- #ifdef OLDCPRIM
- assert(nargs <= 3);
- for (i = nargs; i > 0; i--) {
- arg = vPeek(0);
- moveDataToRegister(arg, i, DataBrand);
- (void) vPop();
- }
- if (nargs < 3) preemptReg(nargs+1, 3 - nargs);
- preemptReg(regs_scratch, 1);
- generateCallC(nargs, name, isExpression);
- freeReg(regs_arg1, nargs);
- #else
- preemptReg(regs_arg1, 1);
- emit("\tmovl\t%s_kernelsp,%s\n", GLOBALVARINDICATOR, RN(regs_arg1));
- mypusher = pusher;
- mypusher.value.address.base = regs_arg1;
- for (i = 0; i < nargs; i++) {
- arg = vPeek(0);
- emitMove(arg->data, mypusher, 'l');
- (void) vPop();
- }
- preemptReg(regs_scratch, 1);
- generateCallC(nargs, name, isExpression);
- #endif
- if (isExpression) {
- claimReg(resultRegister, 1, DataBrand);
- result.data = buildRegisterDD(resultRegister);
- vPush(result);
- }
- }
-
- void doPrimitive(theObject, node, pnode, self, nargs, isExpression, c)
- NodePtr theObject, node, pnode;
- Variable *self;
- int nargs;
- Boolean isExpression;
- Context c;
- {
- if (pnode->tag == P_INTLIT) {
- generateAMachineLanguagePrimitive(theObject, node, atoi(pnode->b.intlit.string),
- self, nargs, isExpression, c);
- } else if (pnode->tag == P_STRINGLIT) {
- /*
- * The C procedure needs to figure out for itself if "self" is a local or
- * global object.
- */
- generateACPrimitive(pnode->b.stringlit.string, nargs, isExpression, c);
- } else {
- assert(FALSE);
- }
- }
-