work in progress
[fw/sdcc] / src / xa51 / gen.c
index 74f0947db8789e2193907fd299c81439e7fe1dc3..ec4e935630ec18396faf23eca82084672758172d 100755 (executable)
@@ -76,6 +76,7 @@ static struct
     short debugLine;
     short stackExtend;
     short nRegsSaved;
+    short parmsPushed;
     set *sendSet;
   }
 _G;
@@ -142,9 +143,7 @@ static void emitcode (char *inst, char *fmt,...) {
 
 char *getStackOffset(int stack) {
   static char gsoBuf[1024];
-  sprintf (gsoBuf, "r7+(%d%+d%+d%+d)", stack,
-          FUNC_ISISR(currFunc->type) ? 
-            port->stack.isr_overhead : port->stack.call_overhead,
+  sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
           currFunc->stack, _G.nRegsSaved);
   return gsoBuf;
 }
@@ -559,7 +558,7 @@ char * printOp (operand *op) {
   } else if (IS_VALOP(op)) {
     opRegName(op, 0, line, 1);
   } else if (IS_TYPOP(op)) {
-    sprintf (line, "[");
+    sprintf (line, "(");
     if (isPtr) {
       if (DCL_TYPE(optype)==FPOINTER)
        strcat (line, "far * ");
@@ -576,7 +575,7 @@ char * printOp (operand *op) {
     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
     strcat (line, nounName(operandType(op)));
-    strcat (line, "]");
+    strcat (line, ")");
   } else {
     bailOut("printOp: unexpected operand type");
   }
@@ -705,35 +704,43 @@ static void genIpush (iCode * ic) {
 
   printIc ("genIpush", ic, 0,1,0);
   aopOp(left,FALSE,FALSE);
+
+
   if (AOP_TYPE(left)==AOP_LIT) {
     switch (AOP_SIZE(left)) 
       {
       case 1:
        emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
        emitcode ("push", "r1l");
+       _G.parmsPushed++;
        return;
       case 2:
        emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
        emitcode ("push", "r1");
+       _G.parmsPushed++;
        return;
       case 3:
        emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
        emitcode ("push", "r1l");
        emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
        emitcode ("push", "r1");
+       _G.parmsPushed += 2;
        return;
       case 4:
        emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
        emitcode ("push", "r1");
        emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
        emitcode ("push", "r1");
+       _G.parmsPushed += 2;
        return;
       }
   } else {
     if (AOP_SIZE(left)>2) {
       emitcode ("push", "%s", AOP_NAME(left)[1]);
+      _G.parmsPushed++;
     }
     emitcode ("push", "%s", AOP_NAME(left)[0]);
+    _G.parmsPushed++;
   }
 }
 
@@ -755,6 +762,12 @@ static void genCall (iCode * ic) {
            printOp (IC_RESULT(ic)));
   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
 
+  /* readjust the stack if we have pushed some parms */
+  if (_G.parmsPushed) {
+    emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
+    _G.parmsPushed=0;
+  }
+
   /* if we need to assign a result value */
   if (IS_ITEMP (IC_RESULT(ic)) &&
       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
@@ -857,18 +870,20 @@ static void genRet (iCode * ic) {
     case 4:
       emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
-      return;
+      break;
     case 3:
       emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
       // fall through
     case 2:
       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
-      return;
+      break;
     case 1:
       emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
-      return;
+      break;
+    default:
+      bailOut("genRet");
     }
-  bailOut("genRet");
+  emitcode ("jmp", "%05d$", returnLabel->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -879,7 +894,7 @@ static void genLabel (iCode * ic) {
   if (IC_LABEL (ic) == entryLabel)
     return;
 
-  emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
+  emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
 }
 
@@ -887,7 +902,7 @@ static void genLabel (iCode * ic) {
 /* genGoto - generates a jmp                                      */
 /*-----------------------------------------------------------------*/
 static void genGoto (iCode * ic) {
-  emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
+  emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
 }
 
@@ -1388,8 +1403,8 @@ static void genIfx (iCode * ic, iCode * popIc) {
   symbol *jlbl, *tlbl;
   operand *cond=IC_COND(ic);
 
-  emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
-           printOp(cond),
+  emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
+           ic->lineno, printOp(cond),
            IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
            IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
 
@@ -1406,7 +1421,7 @@ static void genIfx (iCode * ic, iCode * popIc) {
   switch (AOP_TYPE(cond) )
     {
     case AOP_BIT:
-      emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
+      emitcode (trueOrFalse ? "jb" : "jnb", "%s,%05d$", 
                AOP_NAME(cond)[0], jlbl->key+100);
       return;
     case AOP_REG:
@@ -1547,9 +1562,143 @@ static void genJumpTab (iCode * ic) {
 /* genCast - gen code for casting                                  */
 /*-----------------------------------------------------------------*/
 static void genCast (iCode * ic) {
+  int size;
+  operand *result=IC_RESULT(ic);
+  operand *right=IC_RIGHT(ic);
+  sym_link *ctype=operandType(IC_LEFT(ic));
+  sym_link *rtype=operandType(IC_RIGHT(ic));
+  sym_link *etype=getSpec(rtype);
+  short ptrType, signedness;
+
   printIc ("genCast", ic, 1,1,1);
+
+  aopOp(result, TRUE, TRUE);
+  aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
+  size=AOP_SIZE(result);
+  
+  /* if result is a bit */
+  if (AOP_TYPE(result) == AOP_BIT) {
+    /* if right is literal, we know what the value is */
+    if (AOP_TYPE(right) == AOP_LIT) {
+      if (operandLitValue(right)) {
+       emitcode ("setb", AOP_NAME(result)[0]);
+      } else {
+       emitcode ("clr", AOP_NAME(result)[0]);
+      }
+      return;
+    }
+    /* if right is also a bit */
+    if (AOP_TYPE(right) == AOP_BIT) {
+      emitcode ("mov", "c,%s", AOP_NAME(right));
+      emitcode ("mov", "%s,c", AOP_NAME(result));
+      return;
+    }
+    /* we need to or */
+    emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
+    return;
+  }
+
+  /* if right is a bit */
+  if (AOP_TYPE(right)==AOP_BIT) {
+    emitcode ("mov", "c,%s", AOP_NAME(right));
+    emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
+    emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
+    if (size>2) {
+      emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
+    }
+    return;
+  }
+
+  /* if the result is of type pointer */
+  if (IS_PTR (ctype)) {
+
+    if (AOP_SIZE(right)>1) {
+      emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
+    } else {
+      emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
+      emitcode ("sext", "r1h");
+      emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
+    }
+    
+    /* if pointer to generic pointer */
+    if (IS_GENPTR (ctype)) {
+            
+      if (IS_GENPTR (rtype)) {
+       bailOut("genCast: gptr -> gptr");
+      }
+
+      if (IS_PTR (rtype)) {
+       ptrType = DCL_TYPE (rtype);
+      } else {
+       /* we have to go by the storage class */
+       if (!SPEC_OCLS(etype)) {
+         bailOut("genCast: unknown storage class");
+       } else {
+         ptrType = PTR_TYPE (SPEC_OCLS (etype));
+       }
+      }
+      
+      /* the generic part depends on the type */
+      switch (ptrType)
+       {
+       case POINTER:
+         emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
+         break;
+       case FPOINTER:
+         emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
+         break;
+       case CPOINTER:
+         emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
+         break;
+       default:
+         bailOut("genCast: got unknown storage class");
+       }
+    }
+    return;
+  }
+
+  /* do we have to sign extend? */
+  signedness = SPEC_USIGN(rtype);
+
+  /* now depending on the size */
+  switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
+    {
+    case 0x44:
+    case 0x33:
+      emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+      // fall through
+    case 0x24:
+    case 0x22:
+    case 0x11:
+      emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+      return;
+    case 0x41:
+    case 0x21:
+      emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
+      if (signedness) {
+       emitcode("sext", "r1h");
+      } else {
+       emitcode("mov", "rlh,#0");
+      }
+      emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
+      if (size==2)
+       return;
+      // fall through: case 0x41
+      emitcode("sext", AOP_NAME(result)[1]);
+      return;
+    case 14:
+    case 12:
+      emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
+      emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
+      return;
+    case 24:
+      emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+      return;
+    }
+  bailOut("genCast: unknown size");
 }
 
+
 /*-----------------------------------------------------------------*/
 /* genDjnz - generate decrement & jump if not zero instrucion      */
 /*-----------------------------------------------------------------*/