+ char buff[5];
+ SNPRINTF (buff, sizeof(buff),
+ "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
+ aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
+ }
+}
+
+// The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
+// generates the result if possible. If result is generated, returns TRUE; otherwise
+// returns false and caller must deal with fact that result isn't aopOp'd.
+bool aopOp3(iCode * ic)
+{
+ bool dp1InUse, dp2InUse;
+ bool useDp2;
+
+ // First, generate the right opcode. DPTR may be used if neither left nor result are
+ // of type AOP_STR.
+
+// D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
+// AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
+// AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
+// AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
+// );
+// D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
+// AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
+// AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
+// AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
+// );
+
+
+ // Right uses DPTR unless left or result is an AOP_STR.
+ aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
+
+ // if the right used DPTR, left MUST use DPTR2.
+ // if the right used DPTR2, left MUST use DPTR.
+ // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
+ // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
+ // enabling us to assign DPTR to result.
+
+ if (AOP_USESDPTR(IC_RIGHT(ic)))
+ {
+ useDp2 = TRUE;
+ }
+ else if (AOP_USESDPTR2(IC_RIGHT(ic)))
+ {
+ useDp2 = FALSE;
+ }
+ else
+ {
+ if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
+ {
+ useDp2 = TRUE;
+ }
+ else
+ {
+ useDp2 = FALSE;
+ }
+ }
+
+ aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
+
+ // We've op'd the left & right. So, if left or right are the same operand as result,
+ // we know aopOp will succeed, and we can just do it & bail.
+ if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
+ isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
+ {
+// D(emitcode(";", "aopOp3: (left | right) & result equal"););
+ aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+ return TRUE;
+ }
+
+ // Note which dptrs are currently in use.
+ dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
+ dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
+
+ // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
+ // generate it.
+ if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
+ {
+ return FALSE;
+ }
+
+ // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
+ if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
+ {
+ return FALSE;
+ }
+
+ // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
+ if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
+ {
+ return FALSE;