- // we have to do a signed multiply
-
- //emitcode (";", "signed");
- emitcode ("clr", "F0"); // reset sign flag
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
-
- lbl=newiTempLabel(NULL);
- emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
- // left side is negative, 8-bit two's complement, this fails for -128
- emitcode ("setb", "F0"); // set sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
-
- emitcode ("", "%05d$:", lbl->key+100);
-
- /* if literal */
- if (AOP_TYPE(right)==AOP_LIT) {
- signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
- /* AND literal negative */
- if (val < 0) {
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("mov", "b,#0x%02x", -val);
- } else {
- emitcode ("mov", "b,#0x%02x", val);
- }
- } else {
- lbl=newiTempLabel(NULL);
- emitcode ("mov", "b,a");
- emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
- // right side is negative, 8-bit two's complement
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", lbl->key+100);
- }
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+ pushedB = pushB ();
+
+ if (size == 1 /* no, this is not a bug; with a 1 byte result there's
+ no need to take care about the signedness! */
+ || (lUnsigned && rUnsigned))
+ {
+ /* just an unsigned 8 * 8 = 8 multiply
+ or 8u * 8u = 16u */
+ /* emitcode (";","unsigned"); */
+ /* TODO: check for accumulator clash between left & right aops? */
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* moving to accumulator first helps peepholes */
+ MOVA (aopGet (left, 0, FALSE, FALSE));
+ emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+ }
+ else
+ {
+ emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+ MOVA (aopGet (left, 0, FALSE, FALSE));
+ }
+
+ emitcode ("mul", "ab");
+ aopPut (result, "a", 0);
+ if (size == 2)
+ aopPut (result, "b", 1);
+
+ popB (pushedB);
+ return;
+ }
+
+ /* we have to do a signed multiply */
+ /* emitcode (";", "signed"); */
+
+ /* now sign adjust for both left & right */
+
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
+
+ if (!lUnsigned)
+ {
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign = TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ if (!rUnsigned)
+ {
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign ^= TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
+ }
+
+ /* save the signs of the operands */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned) /* emitcode (";", "signed"); */
+ emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+ else
+ {
+ MOVA (aopGet (right, 0, FALSE, FALSE));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitLabel (lbl);
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+ if (!lUnsigned && val < 0)
+ emitcode ("mov", "a,#0x%02x", -val);
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ MOVA (aopGet (left, 0, FALSE, FALSE));
+
+ if (!lUnsigned)
+ {
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitLabel (lbl);
+ }
+ }
+
+ /* now the multiplication */