]> git.gag.com Git - fw/sdcc/commitdiff
* src/port.h,
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 6 Nov 2003 07:16:24 +0000 (07:16 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 6 Nov 2003 07:16:24 +0000 (07:16 +0000)
* src/hc08/main.c,
* src/mcs51/main.c,
* src/ds390/main.c,
* src/z80/main.c,
* src/avr/main.c,
* src/pic/main.c,
* src/pic16/main.c,
* src/xa51/main.c: added hasExtBitOp & oclsExpense functions to ports
* src/SDCCicode.c: changed several IS_FARSPACE tests to isOclsExpensive
tests (which uses the port's oclsExpense function)
* src/SDCC.y,
* src/SDCCast.c,
* src/SDCCicode.c,
* src/hc08/gen.c,
* src/ds390/gen.c,
* src/mcs51/gen.c: added support for the SWAP iCode (RFE #834167)

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

16 files changed:
ChangeLog
src/SDCC.y
src/SDCCast.c
src/SDCCicode.c
src/avr/main.c
src/ds390/gen.c
src/ds390/main.c
src/hc08/gen.c
src/hc08/main.c
src/mcs51/gen.c
src/mcs51/main.c
src/pic/main.c
src/pic16/main.c
src/port.h
src/xa51/main.c
src/z80/main.c

index 0be62c655ae744bea41047ab45217413d1cf40a3..ea172b90ca65e0d021110207396a04c0dce16ab2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2003-11-06 Erik Petrich <epetrich@ivorytower.norman.ok.us>
+
+       * src/port.h,
+       * src/hc08/main.c,
+       * src/mcs51/main.c,
+       * src/ds390/main.c,
+       * src/z80/main.c,
+       * src/avr/main.c,
+       * src/pic/main.c,
+       * src/pic16/main.c,
+       * src/xa51/main.c: added hasExtBitOp & oclsExpense functions to ports
+       * src/SDCCicode.c: changed several IS_FARSPACE tests to isOclsExpensive
+       tests (which uses the port's oclsExpense function)
+       * src/SDCC.y,
+       * src/SDCCast.c,
+       * src/SDCCicode.c,
+       * src/hc08/gen.c,
+       * src/ds390/gen.c,
+       * src/mcs51/gen.c: added support for the SWAP iCode (RFE #834167)
+        
 2003-11-04 Erik Petrich <epetrich@ivorytower.norman.ok.us>
 
        * src/SDCCcse.c (ifxOptimize),
index 96fbfb1030bdd2a274005a90f2e63a2c86ab3cc6..0dc2de06b448b06d379f157f2ef97bae04339bb1 100644 (file)
@@ -94,7 +94,7 @@ bool uselessDecl = TRUE;
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
 %token RRC RLC 
 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
-%token DUMMY_READ_VOLATILE ENDCRITICAL
+%token DUMMY_READ_VOLATILE ENDCRITICAL SWAP
 
 %type <yyint>  Interrupt_storage
 %type <sym> identifier  declarator  declarator2 enumerator_list enumerator
index 21372879c84969ce60af51745272f6ad92f35ad0..d0ba0c9b26fbabd151b9d0e13e3657df77f0574f 100644 (file)
@@ -52,6 +52,7 @@ static ast *createIval (ast *, sym_link *, initList *, ast *);
 static ast *createIvalCharPtr (ast *, sym_link *, ast *);
 static ast *optimizeCompare (ast *);
 ast *optimizeRRCRLC (ast *);
+ast *optimizeSWAP (ast *);
 ast *optimizeGetHbit (ast *);
 ast *backPatchLabels (ast *, symbol *, symbol *);
 void PA(ast *t);
@@ -1664,6 +1665,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case RRC:
     case RLC:
     case GETHBIT:
+    case SWAP:
       if (IS_AST_SYM_VALUE (pbody->left) &&
          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
        return FALSE;
@@ -2408,6 +2410,11 @@ decorateType (ast * tree)
        ast *wtree = optimizeRRCRLC (tree);
        if (wtree != tree)
          return decorateType (wtree);
+       
+       wtree = optimizeSWAP (tree);
+       if (wtree != tree)
+         return decorateType (wtree);
+        
        // fall through
       }
 
@@ -3008,6 +3015,7 @@ decorateType (ast * tree)
       /*----------------------------*/
     case RRC:
     case RLC:
+    case SWAP:
       TTYPE (tree) = LTYPE (tree);
       TETYPE (tree) = LETYPE (tree);
       return tree;
@@ -4346,6 +4354,11 @@ optimizeGetHbit (ast * tree)
   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
     return tree;
+      
+  /* make sure the port supports GETHBIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+    return tree;
 
   return decorateType (newNode (GETHBIT, tree->left->left, NULL));
 
@@ -4398,6 +4411,11 @@ optimizeRRCRLC (ast * root)
          (getSize (TTYPE (root->left->left)) * 8 - 1))
        goto tryNext0;
 
+      /* make sure the port supports RLC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+        return root;
+
       /* whew got the first case : create the AST */
       return newNode (RLC, root->left->left, NULL);
     }
@@ -4428,6 +4446,11 @@ tryNext0:
          (getSize (TTYPE (root->left->left)) * 8 - 1))
        goto tryNext1;
 
+      /* make sure the port supports RLC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+        return root;
+
       /* whew got the first case : create the AST */
       return newNode (RLC, root->left->left, NULL);
 
@@ -4459,6 +4482,11 @@ tryNext1:
          (getSize (TTYPE (root->left->left)) * 8 - 1))
        goto tryNext2;
 
+      /* make sure the port supports RRC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+        return root;
+
       /* whew got the first case : create the AST */
       return newNode (RRC, root->left->left, NULL);
 
@@ -4489,6 +4517,11 @@ tryNext2:
          (getSize (TTYPE (root->left->left)) * 8 - 1))
        return root;
 
+      /* make sure the port supports RRC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+        return root;
+
       /* whew got the first case : create the AST */
       return newNode (RRC, root->left->left, NULL);
 
@@ -4498,6 +4531,61 @@ tryNext2:
   return root;
 }
 
+/*-----------------------------------------------------------------*/
+/* optimizeSWAP :- optimize for nibble/byte/word swaps             */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeSWAP (ast * root)
+{
+  /* will look for trees of the form
+     (?expr << 4) | (?expr >> 4) or
+     (?expr >> 4) | (?expr << 4) will make that
+     into a SWAP : operation ..
+     note : by 4 I mean (number of bits required to hold the
+     variable /2 ) */
+  /* if the root operations is not a | operation the not */
+  if (!IS_BITOR (root))
+    return root;
+
+  /* (?expr << 4) | (?expr >> 4) */
+  if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
+      || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
+    {
+
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+       return root;
+
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+         !IS_AST_LIT_VALUE (root->right->right))
+       return root;
+
+      /* make sure it is the same expression */
+      if (!isAstEqual (root->left->left,
+                      root->right->left))
+       return root;
+
+      if (AST_LIT_VALUE (root->left->right) !=
+         (getSize (TTYPE (root->left->left)) * 4))
+       return root;
+
+      if (AST_LIT_VALUE (root->right->right) !=
+         (getSize (TTYPE (root->left->left)) * 4))
+       return root;
+
+      /* make sure the port supports SWAP */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
+        return root;
+
+      /* found it : create the AST */
+      return newNode (SWAP, root->left->left, NULL);
+    }
+
+
+  /* not found return root */
+  return root;
+}
+
 /*-----------------------------------------------------------------*/
 /* optimizeCompare - otimizes compares for bit variables     */
 /*-----------------------------------------------------------------*/
@@ -5182,6 +5270,12 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                fprintf(outfile,")\n");
                ast_print(tree->left,outfile,indent+2);
                return ;
+       case SWAP:
+               fprintf(outfile,"SWAP (%p) type (",tree);
+               printTypeChain(tree->ftype,outfile);
+               fprintf(outfile,")\n");
+               ast_print(tree->left,outfile,indent+2);
+               return ;
        case GETHBIT:
                fprintf(outfile,"GETHBIT (%p) type (",tree);
                printTypeChain(tree->ftype,outfile);
index ad97a2a841362c9501e43bcede858128dcac233d..dbb17c25dfd76296f8aa476272c1178ba7c036b4 100644 (file)
@@ -1021,6 +1021,21 @@ isOperandOnStack (operand * op)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output     */
+/*                   storage class are expensive                   */
+/*-----------------------------------------------------------------*/
+bool 
+isOclsExpensive (struct memmap *oclass)
+{
+  if (port->oclsExpense)
+    return port->oclsExpense (oclass) > 0;
+
+  /* In the absence of port specific guidance, assume only */
+  /* farspace is expensive. */
+  return IN_FARSPACE (oclass);
+}
+
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
@@ -1479,6 +1494,7 @@ operandFromSymbol (symbol * sym)
      register equivalent for a local symbol */
   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+      !TARGET_IS_HC08 &&
       (!(options.model == MODEL_FLAT24)) ) &&
       options.stackAuto == 0)
     ok = 0;
@@ -1758,7 +1774,7 @@ geniCodeRValue (operand * op, bool force)
   /* if this is not a temp symbol then */
   if (!IS_ITEMP (op) &&
       !force &&
-      !IN_FARSPACE (SPEC_OCLS (etype)))
+      !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
     {
       op = operandFromOperand (op);
       op->isaddr = 0;
@@ -1767,7 +1783,7 @@ geniCodeRValue (operand * op, bool force)
 
   if (IS_SPEC (type) &&
       IS_TRUE_SYMOP (op) &&
-      (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+      (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
       (options.model == MODEL_FLAT24) ))
     {
       op = operandFromOperand (op);
@@ -2861,11 +2877,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   else if (compareType (ltype, rtype) < 0)
     right = geniCodeCast (ltype, right, TRUE);
 
-  /* if left is a true symbol & ! volatile
+  /* If left is a true symbol & ! volatile
      create an assignment to temporary for
      the right & then assign this temporary
-     to the symbol this is SSA . isn't it simple
-     and folks have published mountains of paper on it */
+     to the symbol. This is SSA (static single
+     assignment). Isn't it simple and folks have
+     published mountains of paper on it */
   if (IS_TRUE_SYMOP (left) &&
       !isOperandVolatile (left, FALSE) &&
       isOperandGlobal (left))
@@ -3094,7 +3111,7 @@ geniCodeReceive (value * args)
          if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
            {
 
-             if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+             if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
                  options.stackAuto == 0 &&
                  (!(options.model == MODEL_FLAT24)) )
                {
@@ -3757,6 +3774,7 @@ ast2iCode (ast * tree,int lvl)
     case '~':
     case RRC:
     case RLC:
+    case SWAP:
       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
 
     case '!':
index e60bcec632f86e3d07a33708832d1b07ed3767b1..b5f958cab46ea8abe66d15c373f8839fef5c2db9 100644 (file)
@@ -131,6 +131,29 @@ _avr_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
        return TRUE;
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      || op == GETHBIT
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -221,6 +244,8 @@ PORT avr_port = {
         NULL,
        NULL,
         NULL,
+       hasExtBitOp,            /* hasExtBitOp */
+       oclsExpense,            /* oclsExpense */
        FALSE,
        TRUE,                   /* little endian */
        0,                      /* leave lt */
index b5ffdff7a2c1fc108ad99d4a25e657f926cd543f..8a55bcd48a28acfc369a97e779ea3a537a78e460 100644 (file)
@@ -7331,6 +7331,65 @@ genGetHbit (iCode * ic)
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes               */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genSwap",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, AOP_USESDPTR(left));
+  
+  _startLazyDPSEvaluation ();
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      emitcode ("swap", "a");
+      aopPut (AOP (result), "a", 0);
+      break;
+    case 2: /* swap bytes in word */
+      if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+       {
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), "a", 1);
+       }
+      else if (operandsEqu (left, result))
+       {
+          char * reg = "a";
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+         if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
+           {
+             emitcode ("mov", "b,a");
+              reg = "b";
+              _G.bInUse=1;
+            }
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), reg, 1);
+          _G.bInUse=0;
+       }
+      else
+       {
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
+       }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+  _endLazyDPSEvaluation ();
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -13119,6 +13178,10 @@ gen390Code (iCode * lic)
        case ENDCRITICAL:
          genEndCritical (ic);
          break;
+       
+        case SWAP:
+         genSwap (ic);
+         break;
           
 #if 0 // obsolete, and buggy for != xdata
        case ARRAYINIT:
index 330b8d7e7d2a1ec48da4c7cb3af941ac0f719154..665770448d03ea9430efeacf14f06b3a87152d63 100644 (file)
@@ -314,6 +314,30 @@ bool _ds390_nativeMulCheck(iCode *ic, sym_link *left, sym_link *right)
     return FALSE; // #STUB
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      || op == GETHBIT
+      || (op == SWAP && size <= 2)
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 
 /** $1 is always the basename.
     $2 is always the output file.
@@ -411,6 +435,8 @@ PORT ds390_port =
   NULL,
   NULL,
   _ds390_nativeMulCheck,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
@@ -702,6 +728,8 @@ PORT tininative_port =
   NULL,
   NULL,
   NULL,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
@@ -911,6 +939,8 @@ PORT ds400_port =
   NULL,
   NULL,
   _ds390_nativeMulCheck,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
index 284fa042d70e201f2c92d3d8cc7d8e7ce1aa3c53..1a71fd2e4e99551f334da00258a41017c20321a4 100644 (file)
@@ -4968,7 +4968,55 @@ genGetHbit (iCode * ic)
   emitcode ("rola", "");
   hc08_dirtyReg (hc08_reg_a, FALSE);
   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+  hc08_freeReg (hc08_reg_a);
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes               */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genSwap",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
   
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      loadRegFromAop (hc08_reg_a, AOP (left), 0);
+      emitcode ("nsa", "");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      storeRegToAop (hc08_reg_a, AOP (result), 0);
+      hc08_freeReg (hc08_reg_a);
+      break;
+    case 2: /* swap bytes in a word */
+      if (operandsEqu (left, result))
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), 0);
+          hc08_useReg (hc08_reg_a);
+          transferAopAop (AOP (left), 1, AOP (result), 0);
+          storeRegToAop (hc08_reg_a, AOP (result), 1);
+          hc08_freeReg (hc08_reg_a);
+        }
+      else
+        {
+          transferAopAop (AOP (left), 0, AOP (result), 1);
+          transferAopAop (AOP (left), 1, AOP (result), 0);
+        }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+    
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
@@ -7629,6 +7677,10 @@ genhc08Code (iCode * lic)
        case ENDCRITICAL:
          genEndCritical (ic);
          break;
+       
+        case SWAP:
+         genSwap (ic);
+          break;
 
        default:
          ic = ic;
index 600e768d38bb9810bdd2671bcccc9695f34941c4..86e75757910960334e85cc174a2f8c2daf4284e0 100644 (file)
@@ -276,6 +276,39 @@ static bool cseCostEstimation (iCode *ic, iCode *pdic)
 }
 
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      || op == GETHBIT
+      || (op == SWAP && size <= 2)
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  /* The hc08's addressing modes allow access to all storage classes */
+  /* inexpensively (<=0) */
+  
+  if (IN_DIRSPACE (oclass))    /* direct addressing mode is fastest */
+    return -2;
+  if (IN_FARSPACE (oclass))    /* extended addressing mode is almost at fast */
+    return -1;
+  if (oclass == istack) /* stack is the slowest, but still faster than */
+    return 0;          /* trying to copy to a temp location elsewhere */
+  
+  return 0; /* anything we missed */
+}
+
+
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -374,6 +407,8 @@ PORT hc08_port =
   NULL,                                /* process_pragma */
   NULL,                                /* getMangledFunctionName */
   NULL,                                /* hasNativeMulFor */
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   TRUE,                                /* use_dw_for_init */
   FALSE,                       /* little endian */
   0,                           /* leave lt */
index 7f254ef7faf3b57d2bac33429a1d464dac8a36f7..fe03434297fe9da4c5d66787bc1a39e93e4fe314 100644 (file)
@@ -5751,6 +5751,66 @@ genGetHbit (iCode * ic)
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes               */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genSwap",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+  
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+      emitcode ("swap", "a");
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      break;
+    case 2: /* swap bytes in word */
+      if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+       {
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
+       }
+      else if (operandsEqu (left, result))
+       {
+          char * reg = "a";
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+         if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
+           {
+             emitcode ("mov", "b,a");
+              reg = "b";
+            }
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
+       }
+      else
+       {
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
+                 1, isOperandVolatile (result, FALSE));
+       }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+    
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -9335,6 +9395,10 @@ gen51Code (iCode * lic)
          genEndCritical (ic);
          break;
 
+       case SWAP:
+         genSwap (ic);
+         break;
+
        default:
          ic = ic;
        }
index 30adbfd850308cee8f7fefcbd0bf22d97fcb4729..dfda28221c3e92b2343fd3c97df685d965436136 100644 (file)
@@ -202,6 +202,30 @@ static bool cseCostEstimation (iCode *ic, iCode *pdic)
     return 1;
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      || op == GETHBIT
+      || (op == SWAP && size <= 2)
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -299,6 +323,8 @@ PORT mcs51_port =
   NULL,
   NULL,
   NULL,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
index 2a818bf36b73be8319e72e9aaf0ca81bb23abbf2..b3515d09d77c8f1b95b14dd4db5e0eaad261a8b0 100644 (file)
@@ -320,6 +320,32 @@ _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
 */
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  /* The IN_FARSPACE test is compatible with historical behaviour, */
+  /* but I don't think it is applicable to PIC. If so, please feel */
+  /* free to remove this test -- EEP */
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -423,6 +449,8 @@ PORT pic_port =
   _process_pragma,                             /* process a pragma */
   NULL,
   _hasNativeMulFor,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
index d41540df164003a7ae6cffa13e7752ad09ce08cf..e1c6f24c16c78ad56277e5d32b48255f366e3578 100644 (file)
@@ -381,6 +381,32 @@ _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
 */
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  /* The IN_FARSPACE test is compatible with historical behaviour, */
+  /* but I don't think it is applicable to PIC. If so, please feel */
+  /* free to remove this test -- EEP */
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -488,6 +514,8 @@ PORT pic16_port =
   _process_pragma,                             /* process a pragma */
   NULL,
   _hasNativeMulFor,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   FALSE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
index 3e3aec9411ad99a1129379e54d36c05b93abc5df..3f1745ec867db93432b90590d0a9ec883243375d 100644 (file)
@@ -249,6 +249,16 @@ typedef struct
     */
     bool (*hasNativeMulFor) (iCode *ic, sym_link *left, sym_link *right);
 
+    /** Returns true if the port has implemented certain bit
+        manipulation iCodes (RRC, RLC, SWAP, GETHBIT)
+    */
+    bool (*hasExtBitOp) (int op, int size);
+    
+    /** Returns the relative expense of accessing a particular output
+        storage class. Larger values indicate higher expense.
+    */
+    int (*oclsExpense) (struct memmap *oclass);
+    
     /** If TRUE, then tprintf and !dw will be used for some initalisers
      */
     bool use_dw_for_init;
index 1a9ae3edcf56aa8326092f9e59f1dbb1b8294c9d..3ef77a26dcbb9a3fd1625b5517b7ba5ed08eb518 100755 (executable)
@@ -192,6 +192,30 @@ static bool cseCostEstimation (iCode *ic, iCode *pdic)
     return 1;
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == RRC
+      || op == RLC
+      || op == GETHBIT
+     )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
+
 /** $1 is always the basename.
     $2 is always the output file.
     $3 varies
@@ -294,6 +318,8 @@ PORT xa51_port =
   NULL, // process_pragma()
   NULL, // getMangledFunctionName()
   NULL, // hasNativeMulFor()
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   TRUE, // use_dw_for_init
   TRUE,                                /* little endian */
   0,                           /* leave lt */
index 2768d4d6698fae48837627737598c12472bd9019..3545430f3500f6351e94603041991bd5535e5cec 100644 (file)
@@ -478,6 +478,26 @@ _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
   return FALSE;
 }
 
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+  if (op == GETHBIT)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+  if (IN_FARSPACE(oclass))
+    return 1;
+    
+  return 0;
+}
+
 
 #define LINKCMD "link-{port} -nf {dstfilename}"
 /*
@@ -573,6 +593,8 @@ PORT z80_port =
   _process_pragma,
   _mangleSupportFunctionName,
   _hasNativeMulFor,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   TRUE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */
@@ -670,6 +692,8 @@ PORT gbz80_port =
   _process_pragma,
   _mangleSupportFunctionName,
   _hasNativeMulFor,
+  hasExtBitOp,                 /* hasExtBitOp */
+  oclsExpense,                 /* oclsExpense */
   TRUE,
   TRUE,                                /* little endian */
   0,                           /* leave lt */