]> git.gag.com Git - fw/sdcc/commitdiff
* src/pic16/gen.c (genGenericShift) added handling of differently
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 5 Jan 2005 12:20:09 +0000 (12:20 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 5 Jan 2005 12:20:09 +0000 (12:20 +0000)
  sized left operand and result

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3628 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/pic16/gen.c

index eee080e71a775ec71a9f3332756dccc1a21ad984..3c809247a27b8445815c4e17f3d60439b889d18d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-01-05 Raphael Neider <rneider AT web.de>
+
+        * src/pic16/gen.c (genGenericShift) added handling of differently
+         sized left operand and result
+
 2005-01-04 Raphael Neider <rneider AT web.de>
 
        * src/pic16/gen.c (genIfxJump) fixed inverted skips on CARRY
index 1a58c9cb431f3cd39ba54499a41e67221c3741ee..7646de4f02c0bcd0fc4a5d959a6580a29a87c1e3 100644 (file)
@@ -10604,9 +10604,7 @@ static void genGenericShift (iCode *ic, int isShiftLeft) {
    * Note: we perform arithmetic shifts if the left operand is
    * signed and we do an (effective) right shift, i. e. we
    * shift in the sign bit from the left. */
-  
-  assert (AOP_SIZE(result) == AOP_SIZE(left));
-
+   
   label_complete = newiTempLabel ( NULL );
   label_loop_pos = newiTempLabel ( NULL );
   label_loop_neg = NULL;
@@ -10620,11 +10618,31 @@ static void genGenericShift (iCode *ic, int isShiftLeft) {
     label_negative = newiTempLabel ( NULL );
   } // if
 
-  // copy source to result
-  for (offset=0; offset < AOP_SIZE(result); offset++) {
+  // copy source to result -- this will effectively truncate the left operand to the size of result!
+  // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
+  // This is fine, as it only occurs for left shifting with negative count which is not standardized!
+  for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
     mov2f (AOP(result),AOP(left), offset);
   } // for
 
+  // if result is longer than left, fill with zeros (or sign)
+  if (AOP_SIZE(left) < AOP_SIZE(result)) {
+    if (sign && AOP_SIZE(left) > 0) {
+      // shift signed operand -- fill with sign
+      pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
+      pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
+      pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
+      for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
+        pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
+      } // for
+    } else {
+      // shift unsigned operand -- fill result with zeros
+      for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
+        pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
+      } // for
+    }
+  } // if (size mismatch)
+
   pic16_mov2w (AOP(right), 0);
   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));