* src/ds390/gen.c (genCpl): fixed bit=~(char/bit) bugs, added warning
[fw/sdcc] / src / ds390 / gen.c
index 518e36ccd0355eb121f7039a5d44e15e9effa3ca..945637411fc5bd8701d08d14862e544a79b2c1cc 100644 (file)
@@ -1914,25 +1914,43 @@ genCpl (iCode * ic)
   int offset = 0;
   int size;
   symbol *tlbl;
+  sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
 
-  D (emitcode (";", "genCpl "););
-
+  D(emitcode (";", "genCpl"));
 
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
 
   /* special case if in bit space */
-  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
-    if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
-      emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
-      emitcode ("cpl", "c");
-      emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+    {
+      char *l;
+
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
+          (SPEC_USIGN (letype) && IS_CHAR (letype)))
+        {
+          /* promotion rules are responsible for this strange result:
+             bit -> int -> ~int -> bit
+             uchar -> int -> ~int -> bit
+          */
+          werror(W_COMPLEMENT);
+          emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
       goto release;
     }
     tlbl=newiTempLabel(NULL);
-    emitcode ("cjne", "%s,#0x01,%05d$",
-              aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
+      l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE,NULL);
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
+          AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
+          IS_AOP_PREG (IC_LEFT (ic)))
+        {
+          emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
+        }
+      else
+        {
+          MOVA (l);
+          emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
+        }
     emitcode ("", "%05d$:", tlbl->key+100);
     outBitC (IC_RESULT(ic));
     goto release;