Better packAssign
[fw/sdcc] / src / z80 / gen.c
index 4a1d97379dea1d6b00b8db9e72f351033de082cd..926012163818ee1d4d6b83e7b233a5c584f415f0 100644 (file)
@@ -13,6 +13,9 @@
   With loopInvariant on                                20919   156     19AB
   With loopInduction on                                Breaks          198B
   With all working on                          20796   158     196C
+  Slightly better genCmp(signed)               20597   159     195B
+  Better reg packing, first peephole           20038   163     1873
+  With assign packing                          19281   165     1849
 
   Michael Hope <michaelh@earthling.net>        2000
   Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
@@ -537,18 +540,19 @@ dealloc:
     }
 }
 
-char *aopGetWord(asmop *aop, int offset)
+char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
 {
     char *s = buffer ;
     char *rs;
 
-    assert(aop->size == 2);
+    if (aop->size != 2)
+       return NULL;
     assert(offset == 0);
 
     /* depending on type */
     switch (aop->type) {
     case AOP_IMMD:
-       sprintf (s,"#%s",aop->aopu.aop_immd);
+       sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
@@ -560,7 +564,7 @@ char *aopGetWord(asmop *aop, int offset)
        if (!IS_FLOAT(val->type)) {
            unsigned long v = floatFromVal(val);
 
-           sprintf(buffer,"#0x%04lx", v);
+           sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
            ALLOC_ATOMIC(rs,strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
@@ -571,6 +575,11 @@ char *aopGetWord(asmop *aop, int offset)
     return NULL;
 }
 
+char *aopGetWord(asmop *aop, int offset)
+{
+    return aopGetWordLong(aop, offset, TRUE);
+}
+
 /*-----------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
@@ -1375,16 +1384,30 @@ static bool genPlusIncr (iCode *ic)
     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
         return FALSE;
     
+    emitcode("", "; genPlusIncr");
+
+    icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+
+    /* If result is a pair */
+    if (isPair(AOP(IC_RESULT(ic)))) {
+       char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+       if (left) {
+           /* Both a lit on the right and a true symbol on the left */
+           emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
+           return TRUE;
+       }
+    }
+
     /* if the literal value of the right hand side
        is greater than 4 then it is not worth it */
-    if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
+    if (icount > 4)
         return FALSE ;
 
     /* Inc a pair */
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
        isPair(AOP(IC_RESULT(ic)))) {
        while (icount--) {
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
+           emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
        }
        return TRUE;
     }
@@ -1498,6 +1521,22 @@ static void genPlus (iCode *ic)
 
     size = getDataSize(IC_RESULT(ic));
 
+    /* Special case when left and right are constant */
+    if (isPair(AOP(IC_RESULT(ic)))) {
+       char *left, *right;
+       
+       left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+       right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+       if (left && right) {
+           /* It's a pair */
+           /* PENDING: fix */
+           char buffer[100];
+           sprintf(buffer, "#(%s + %s)", left, right);
+           emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
+           goto release;
+       }
+    }
+
     while(size--) {
        if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
            MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
@@ -1617,7 +1656,6 @@ static void genMinus (iCode *ic)
     size = getDataSize(IC_RESULT(ic));   
 
     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-        CLRC;
     }
     else{
         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
@@ -1628,9 +1666,14 @@ static void genMinus (iCode *ic)
     /* if literal, add a,#-lit, else normal subb */
     while (size--) {
        MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
-       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
-           emitcode("sbc","a,%s",
-                    aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
+           if (!offset)
+               emitcode("sub","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+           else
+               emitcode("sbc","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       }
        else{
            /* first add without previous c */
            if (!offset)
@@ -1753,10 +1796,15 @@ static void genCmp (operand *left,operand *right,
         size = max(AOP_SIZE(left),AOP_SIZE(right));
 
         /* if unsigned char cmp with lit, just compare */
-        if((size == 1) && !sign &&
+        if((size == 1) && 
            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
            emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
-           emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+           if (sign) {
+               emitcode("xor", "a,#0x80");
+               emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
+           }
+           else 
+               emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
         } 
        else {
             if(AOP_TYPE(right) == AOP_LIT) {
@@ -1780,30 +1828,46 @@ static void genCmp (operand *left,operand *right,
                     goto release;
                 }
             }
-           CLRC;
+           if (sign) {
+               /* First setup h and l contaning the top most bytes XORed */
+               bool fDidXor = FALSE;
+               if (AOP_TYPE(left) == AOP_LIT){
+                   unsigned long lit = (unsigned long)
+                       floatFromVal(AOP(left)->aopu.aop_lit);
+                   emitcode("ld", "l,#0x%02x",
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
+                   emitcode("xor", "a,#0x80");
+                   emitcode("ld", "l,a");
+                   fDidXor = TRUE;
+               }
+               if (AOP_TYPE(right) == AOP_LIT) {
+                   unsigned long lit = (unsigned long)
+                       floatFromVal(AOP(right)->aopu.aop_lit);
+                   emitcode("ld", "h,#0x%02x",
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
+                   emitcode("xor", "a,#0x80");
+                   emitcode("ld", "h,a");
+                   fDidXor = TRUE;
+               }
+               if (!fDidXor)
+                   CLRC;
+           }
+           else {
+               CLRC;
+           }
             while (size--) {
                /* Do a long subtract */
-                MOVA(aopGet(AOP(left),offset,FALSE));
+               if (!sign || size) 
+                   MOVA(aopGet(AOP(left),offset,FALSE));
                 if (sign && size == 0) {
-                   /* Ugly but hey */
-                   emitcode("push", "af");
-                   emitcode("xor", "a,#0x80");
-                   emitcode("ld", "l,a");
-                   emitcode("pop", "af");
                    emitcode("ld", "a,l");
-                    if (AOP_TYPE(right) == AOP_LIT){
-                        unsigned long lit = (unsigned long)
-                           floatFromVal(AOP(right)->aopu.aop_lit);
-                        emitcode("sbc","a,#0x%02x",
-                                0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));                       
-                    } else {
-                       emitcode("push", "af");
-                       emitcode("ld", "a,%s",aopGet(AOP(right),offset++,FALSE));
-                       emitcode("xor", "a,#0x80");
-                       emitcode("ld", "l,a");
-                       emitcode("pop", "af");
-                        emitcode("sbc", "a,l");
-                    }
+                   emitcode("sbc", "a,h");
                }
                else {
                    /* Subtract through, propagating the carry */
@@ -3142,6 +3206,7 @@ static void genGenPointerGet (operand *left,
     if (AOP_TYPE(left) == AOP_IMMD)
        emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
     else { /* we need to get it byte by byte */
+       
        emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
        emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
     }
@@ -3396,18 +3461,30 @@ static void genAssign (iCode *ic)
        (AOP_TYPE(result) != AOP_REG) &&
        (AOP_TYPE(right) == AOP_LIT) &&
        !IS_FLOAT(operandType(right)) &&
-       (lit < 256L)){
-       emitcode("xor","a,a");
+       (lit < 256L)) {
+       bool fXored = FALSE;
+       offset = 0;
        /* Work from the top down.
           Done this way so that we can use the cached copy of 0
           in A for a fast clear */
        while (size--) {
-           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
-               aopPut(AOP(result),"a",size);
+           if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
+               if (!fXored && size>1) {
+                   emitcode("xor", "a,a");
+                   fXored = TRUE;
+               }
+               if (fXored) {
+                   aopPut(AOP(result),"a",offset);
+               }
+               else {
+                   aopPut(AOP(result), "#0", offset);
+               }
+           }
            else
                aopPut(AOP(result),
-                      aopGet(AOP(right),size,FALSE),
-                      size);
+                      aopGet(AOP(right),offset,FALSE),
+                      offset);
+           offset++;
        }
     } else {
        while (size--) {
@@ -3833,8 +3910,8 @@ void genZ80Code (iCode *lic)
 
     /* now we are ready to call the 
        peep hole optimizer */
-    /*    if (!options.nopeep)
-         peepHole (&lineHead); */
+    if (!options.nopeep)
+       peepHole (&lineHead);
 
     /* now do the actual printing */
     printLine (lineHead,codeOutFile);