fixed bug #505806
[fw/sdcc] / src / xa51 / gen.c
index 40427b9c3200d14c5ad3f859bc4832daf0bcb8b3..ef5c986c2e6e967dc5a541ac1d3bab5b798cd1c9 100755 (executable)
@@ -1,3 +1,11 @@
+/* The only ops for now are:
+   genAssign
+   genIfx
+   genAddrOf
+   genPointerSet
+   genPointerGet
+*/
+
 /*-------------------------------------------------------------------------
   SDCCgen51.c - source file for code generation for 8051
 
@@ -94,6 +102,16 @@ static lineNode *lineCurr = NULL;
 #define MSB24   2
 #define MSB32   3
 
+static char *MOVB="mov.b";
+static char *MOVW="mov.w";
+static char *MOVCB="movc.b";
+static char *MOVCW="movc.w";
+
+void bailOut (char *mesg) {
+  fprintf (stderr, "%s: bailing out\n", mesg);
+  exit (1);
+}
+
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
@@ -127,6 +145,16 @@ static void emitcode (char *inst, char *fmt,...) {
   va_end (ap);
 }
 
+char *getStackOffset(int stack) {
+  static char gsoBuf[1024];
+  // dit slaat natuurlijk nergens op
+  sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack,
+          FUNC_ISISR(currFunc->type) ? 
+            port->stack.isr_overhead : port->stack.call_overhead,
+          _G.nRegsSaved);
+  return gsoBuf;
+}
+
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
@@ -159,28 +187,29 @@ char *aopTypeName(asmop *aop) {
 /* aopForSym - for a true symbol                                   */
 /*-----------------------------------------------------------------*/
 static asmop *aopForSym(symbol *sym, bool result) {
+  int size;
   asmop *aop;
 
   sym->aop = aop = newAsmop(0);
-  aop->size=getSize(sym->type);
+  size=aop->size=getSize(sym->type);
 
-  // if it is in registers
+  // if the sym has registers
   if (sym->nRegs && sym->regs[0]) {
     aop->type=AOP_REG;
-    if (sym->regs[1]) {
+    sprintf (aop->name[0], sym->regs[0]->name);
+    if (size>2) {
       sprintf (aop->name[1], sym->regs[1]->name);
     }
-    sprintf (aop->name[0], sym->regs[0]->name);
     return aop;
   }
 
   // if it is on stack
   if (sym->onStack) {
     aop->type=AOP_STK;
-    sprintf (aop->name[0], "[r7+%d+0+%d+%d]", sym->stack, 
-            FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
-    sprintf (aop->name[1], "[r7+%d+2+%d+%d]", sym->stack,
-            FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+    sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
+    if (size > 2) {
+      sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
+    }
     return aop;
   }
 
@@ -200,20 +229,23 @@ static asmop *aopForSym(symbol *sym, bool result) {
   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
     aop->type=AOP_DIR;
     sprintf (aop->name[0], sym->rname);
-    sprintf (aop->name[1], "#0x%02x", POINTER);
+    if (size>2) {
+      sprintf (aop->name[0], "%s+2", sym->rname);
+    }
     return aop;
   }
 
   // if in code space
   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
     if (result) {
-      fprintf (stderr, "aopForSym: result can not be in code space\n");
-      exit (1);
+      bailOut("aopForSym: result can not be in code space");
     }
     aop->type=AOP_CODE;
     emitcode ("mov", "r0,#%s", sym->rname);
-    sprintf (aop->name[0], "r0");
-    sprintf (aop->name[1], "#0x%02x", CPOINTER);
+    sprintf (aop->name[0], "[r0]");
+    if (size>2) {
+      sprintf (aop->name[1], "[r0+1]");
+    }
     return aop;
   }
 
@@ -222,23 +254,14 @@ static asmop *aopForSym(symbol *sym, bool result) {
     aop->type=AOP_FAR;
     emitcode ("mov", "r0,#%s", sym->rname);
     sprintf (aop->name[0], "[r0]");
-    if (result) {
-      sprintf (aop->name[1], "[r0+2]");
-    } else {
-      sprintf (aop->name[1], "#0x%02x", FPOINTER);
+    if (size>2) {
+      sprintf (aop->name[1], "[r0+1]");
     }
     return aop;
   }
 
-  // special case for a function
-  if (IS_FUNC (sym->type)) {
-    aop->type=AOP_IMMD;
-    sprintf (aop->name[0], sym->rname);
-    return aop;
-  }
-
-  fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name);
-  exit (1);
+  bailOut("aopForSym");
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
@@ -246,7 +269,7 @@ static asmop *aopForSym(symbol *sym, bool result) {
 /*-----------------------------------------------------------------*/
 static asmop *aopForVal(operand *op) {
   asmop *aop;
-  long v=floatFromVal(OP_VALUE(op));
+  long v=(long long)floatFromVal(OP_VALUE(op));
 
   if (IS_OP_LITERAL(op)) {
     op->aop = aop = newAsmop (AOP_LIT);
@@ -263,8 +286,7 @@ static asmop *aopForVal(operand *op) {
        sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
        break;
       default:
-       fprintf (stderr, "aopForVal (lit): unknown size\n");
-       exit (1);
+       bailOut("aopForVal");
       }
     return aop;
   }
@@ -284,8 +306,7 @@ static asmop *aopForVal(operand *op) {
        return aop;
       }
   }
-  fprintf (stderr, "aopForVal: unknown type\n");
-  exit (1);
+  bailOut ("aopForVal: unknown type");
   return NULL;
 }
 
@@ -297,23 +318,20 @@ static void aopOp(operand *op, bool result) {
   }
   if (IS_VALOP(op)) {
     if (result) {
-      fprintf (stderr, "aopOp: result can not be a value\n");
-      exit (1);
+      bailOut("aopOp: result can not be a value");
     }
     aopForVal (op);
     return;
   }
 
-  fprintf (stderr, "aopOp: unexpected operand\n");
-  exit (1);
+  bailOut("aopOp: unexpected operand");
 }
 
 char *opRegName(operand *op, int offset, char *opName) {
 
   if (IS_SYMOP(op)) {
     if (OP_SYMBOL(op)->onStack) {
-      sprintf (aop->name[0], "[r7+%d+0+%d+%d]", sym->stack, 
-              FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+      sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
       return opName;
     }
     if (IS_TRUE_SYMOP(op))
@@ -321,17 +339,16 @@ char *opRegName(operand *op, int offset, char *opName) {
     else if (OP_SYMBOL(op)->regs[offset])
       return OP_SYMBOL(op)->regs[offset]->name;
     else
-      return "NULL";
+      bailOut("opRegName: unknown regs");
   }
 
   if (IS_VALOP(op)) {
     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
+    case V_SBIT:
     case V_BIT:
       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
          SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
-       fprintf (stderr, "opRegName: invalid bit value (%d)\n",
-                SPEC_CVAL(OP_VALUE(op)->type).v_int);
-       exit (1);
+       bailOut("opRegName: invalid bit value");
       }
       // fall through
     case V_CHAR:
@@ -345,22 +362,21 @@ char *opRegName(operand *op, int offset, char *opName) {
       }
       break;
     case V_FLOAT:
-      sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
+      sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
       break;
     default: 
-      fprintf (stderr, "opRegName: unexpected noun\n");
-      exit (1);
+      bailOut("opRegName: unexpected noun");
     }
     return opName;
   }
-  fprintf (stderr, "opRegName: unexpected operand type\n");
-  exit (1);
-  return NULL; // to keep the compiler happy
+  bailOut("opRegName: unexpected operand type");
+  return NULL;
 }
 
 char * printOp (operand *op) {
   static char line[132];
-  bool isPtr = op->isPtr | op->isGptr;
+  sym_link *optype=operandType(op);
+  bool isPtr = IS_PTR(optype);
 
   if (IS_SYMOP(op)) {
     symbol *sym=OP_SYMBOL(op);
@@ -368,9 +384,24 @@ char * printOp (operand *op) {
       sym=SYM_SPIL_LOC(sym);
     }
     if (isPtr) {
-      sprintf (line, "[%s]:", sym->name);
+      sprintf (line, "[");
+      if (DCL_TYPE(optype)==FPOINTER)
+       strcat (line, "far * ");
+      else if (DCL_TYPE(optype)==CPOINTER)
+       strcat (line, "code * ");
+      else if (DCL_TYPE(optype)==GPOINTER)
+       strcat (line, "gen * ");
+      else if (DCL_TYPE(optype)==POINTER)
+       strcat (line, "near * ");
+      else
+       strcat (line, "unknown * ");
+      strcat (line, "(");
+      strcat (line, nounName(sym->etype));
+      strcat (line, ")");
+      strcat (line, sym->name);
+      strcat (line, "]:");
     } else {
-      sprintf (line, "%s:", sym->name);
+      sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
     }
     if (sym->regs[0]) {
       strcat (line, sym->regs[0]->name);
@@ -381,7 +412,7 @@ char * printOp (operand *op) {
       return line;
     }
     if (sym->onStack) {
-      sprintf (line+strlen(line), "stack+%d", sym->stack);
+      sprintf (line+strlen(line), "stack%+d", sym->stack);
       return line;
     }
     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
@@ -401,15 +432,26 @@ char * printOp (operand *op) {
   } else if (IS_VALOP(op)) {
     opRegName(op, 0, line);
   } else if (IS_TYPOP(op)) {
-    sprintf (line, "(");
+    sprintf (line, "[");
+    if (isPtr) {
+      if (DCL_TYPE(optype)==FPOINTER)
+       strcat (line, "far * ");
+      else if (DCL_TYPE(optype)==CPOINTER)
+       strcat (line, "code * ");
+      else if (DCL_TYPE(optype)==GPOINTER)
+       strcat (line, "gen * ");
+      else if (DCL_TYPE(optype)==POINTER)
+       strcat (line, "near * ");
+      else
+       strcat (line, "unknown * ");
+    }
     // forget about static, volatile, ... for now
     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 {
-    fprintf (stderr, "printOp: unexpected operand type\n");
-    exit (1);
+    bailOut("printOp: unexpected operand type");
   }
   return line;
 }
@@ -417,7 +459,7 @@ char * printOp (operand *op) {
 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
   char line[132];
 
-  sprintf (line, "%s", op);
+  sprintf (line, "%s(%d)", op, ic->lineno);
   if (result) {
     strcat (line, " result=");
     strcat (line, printOp (IC_RESULT(ic)));
@@ -434,7 +476,7 @@ void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
 }
 
 /*-----------------------------------------------------------------*/
-/* toBoolean - return bit for operand!=0                           */
+/* toBoolean - return carry for operand!=0                           */
 /*-----------------------------------------------------------------*/
 static char *toBoolean (operand * op) {
   switch (AOP_SIZE(op)) 
@@ -442,11 +484,11 @@ static char *toBoolean (operand * op) {
     case 1:
     case 2:
       emitcode ("cmp", "%s,#0", AOP_NAME(op));
-      return "z";
+      emitcode ("mov", "c,z");
+      return "c";
     }
 
-  fprintf (stderr, "toBoolean: unknown size %d\n", AOP_SIZE(op));
-  exit (1);
+  bailOut("toBoolean: unknown size");
   return NULL;
 }
 
@@ -542,7 +584,8 @@ static void genIpop (iCode * ic) {
 /* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
 static void genCall (iCode * ic) {
-  emitcode (";", "genCall %s", OP_SYMBOL(IC_LEFT(ic))->name);
+  emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
+           printOp (IC_RESULT(ic)));
 }
 
 /*-----------------------------------------------------------------*/
@@ -600,7 +643,28 @@ genEndFunction (iCode * ic)
 /* genRet - generate code for return statement                     */
 /*-----------------------------------------------------------------*/
 static void genRet (iCode * ic) {
-  emitcode (";", "genRet");
+
+  printIc ("genRet", ic, 0,1,0);
+
+  aopOp(IC_LEFT(ic),FALSE);
+
+  switch (AOP_SIZE(IC_LEFT(ic)))
+    {
+    case 4:
+      emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
+      emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
+      return;
+    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;
+    case 1:
+      emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
+      return;
+    }
+  bailOut("genRet");
 }
 
 /*-----------------------------------------------------------------*/
@@ -616,11 +680,11 @@ static void genLabel (iCode * ic) {
 }
 
 /*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp                                      */
+/* genGoto - generates a jmp                                      */
 /*-----------------------------------------------------------------*/
 static void genGoto (iCode * ic) {
   emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
-  emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
+  emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
 }
 
 /*-----------------------------------------------------------------*/
@@ -662,19 +726,37 @@ static void genMod (iCode * ic) {
 /*-----------------------------------------------------------------*/
 /* genCmpGt :- greater than comparison                             */
 /*-----------------------------------------------------------------*/
-static void genCmpGt (iCode * ic, iCode * ifx) {
+static void genCmpGt (iCode * ic) {
+  printIc ("genCmpGt", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpLe (iCode * ic) {
+  printIc ("genCmpGt", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpGe (iCode * ic) {
+  printIc ("genCmpGt", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpNe (iCode * ic) {
   printIc ("genCmpGt", ic, 1,1,1);
 }
 /*-----------------------------------------------------------------*/
 /* genCmpLt - less than comparisons                                */
 /*-----------------------------------------------------------------*/
-static void genCmpLt (iCode * ic, iCode * ifx) {
+static void genCmpLt (iCode * ic) {
   printIc ("genCmpLt", ic, 1,1,1);
 }
 /*-----------------------------------------------------------------*/
 /* genCmpEq - generates code for equal to                          */
 /*-----------------------------------------------------------------*/
-static void genCmpEq (iCode * ic, iCode * ifx) {
+static void genCmpEq (iCode * ic) {
   printIc ("genCmpEq", ic, 1,1,1);
 }
 
@@ -814,20 +896,184 @@ static void genRightShift (iCode * ic) {
 /* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
 static void genPointerGet (iCode * ic, iCode *pi) {
+  char *instr;
+
+  operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
+
   printIc ("genPointerGet", ic, 1,1,0);
+
+  if (!IS_PTR(operandType(left))) {
+    bailOut ("genPointerGet: pointer required");
+  }
+
+  aopOp(left,FALSE);
+  aopOp(result,TRUE);
+
+  if (IS_GENPTR(operandType(left))) {
+    emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]", 
+             AOP_NAME(result)[0], AOP_NAME(result)[1],
+             AOP_NAME(left)[0], AOP_NAME(left)[1]);
+    return;
+  }
+
+  switch (AOP_TYPE(left)) 
+    {
+    case AOP_CODE:
+      if (AOP_SIZE(result)==1) {
+       instr=MOVCB;
+      } else {
+       instr=MOVCW;
+      }
+      emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+      if (AOP_SIZE(result) > 2) {
+       if (AOP_SIZE(result)==3) {
+         instr=MOVCB;
+       } else {
+         instr=MOVCW;
+       }
+       emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+      }
+      return;
+    case AOP_FAR:
+      if (AOP_SIZE(result)==1) {
+       instr=MOVB;
+      } else {
+       instr=MOVW;
+      }
+      emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+      if (AOP_SIZE(result) > 2) {
+       if (AOP_SIZE(result)==3) {
+         instr=MOVB;
+       } else {
+         instr=MOVW;
+       }
+       emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+      }
+      return;
+    case AOP_DIR:
+      if (AOP_SIZE(result)==1) {
+       instr=MOVB;
+      } else {
+       instr=MOVW;
+      }
+      emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+      if (AOP_SIZE(result) > 2) {
+       if (AOP_SIZE(result)==3) {
+         instr=MOVB;
+       } else {
+         instr=MOVW;
+       }
+       emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
+      }
+      return;
+    case AOP_REG:
+      if (AOP_SIZE(result)==1) {
+       instr=MOVB;
+      } else {
+       instr=MOVW;
+      }
+      emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+      if (AOP_SIZE(result) > 2) {
+       // result is generic pointer
+       sym_link *optype=operandType(left);
+       sym_link *opetype=getSpec(optype);
+       if (IS_PTR(optype) && !IS_GENPTR(optype)) {
+         emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(result)[1], 
+                   PTR_TYPE(SPEC_OCLS(opetype)));
+       } else {
+         emitcode ("mov.b", "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
+       }
+      }
+      return;
+    case AOP_STK:
+      // if both on stack
+      if (AOP_TYPE(result)==AOP_STK) {
+       if (AOP_SIZE(result)==1) {
+         emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
+         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
+       } else {
+         emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
+         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
+       }
+      } else {
+       if (AOP_SIZE(result)==3) {
+         emitcode ("mov.b", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+       } else {
+         emitcode ("mov.w", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
+       }
+      }
+      if (AOP_SIZE(result) > 2) {
+       if (AOP_TYPE(result)==AOP_STK) {
+         if (AOP_SIZE(result)==3) {
+           emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
+           emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
+         } else {
+           emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
+           emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
+         }
+       } else {
+         emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
+       }
+      }
+      return;
+    }
+  bailOut ("genPointerGet: unknown pointer");
 }
 
 /*-----------------------------------------------------------------*/
 /* genPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
 static void genPointerSet (iCode * ic, iCode *pi) {
+  char *instr;
+
+  operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
+
   printIc ("genPointerSet", ic, 1,0,1);
+
+  if (!IS_PTR(operandType(result))) {
+    bailOut ("genPointerSet: pointer required");
+  }
+
+  aopOp(right,FALSE);
+  aopOp(result,TRUE);
+
+  if (IS_GENPTR(operandType(result))) {
+    emitcode (";", "INLINE _gptrset ; [%s %s]=  %s %s", 
+             AOP_NAME(result)[0], AOP_NAME(result)[1],
+             AOP_NAME(right)[0], AOP_NAME(right)[1]);
+    return;
+  }
+
+  switch (AOP_TYPE(result)) 
+    {
+    case AOP_REG:
+    case AOP_DIR:
+    case AOP_FAR:
+    case AOP_STK:
+      if (AOP_SIZE(result)==1) {
+       instr=MOVB;
+      } else {
+       instr=MOVW;
+      }
+      emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+      if (AOP_SIZE(result) > 2) {
+       if (AOP_SIZE(result)==3) {
+         instr=MOVB;
+       } else {
+         instr=MOVW;
+       }
+       emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
+      }
+      return;
+    }
+  bailOut ("genPointerSet: unknown pointer");
 }
 
 /*-----------------------------------------------------------------*/
 /* genIfx - generate code for Ifx statement                        */
 /*-----------------------------------------------------------------*/
 static void genIfx (iCode * ic, iCode * popIc) {
+  char *instr;
   bool trueOrFalse;
   symbol *jlbl, *tlbl;
   operand *cond=IC_COND(ic);
@@ -856,24 +1102,70 @@ static void genIfx (iCode * ic, iCode * popIc) {
     case AOP_REG:
     case AOP_DIR:
     case AOP_FAR:
+    case AOP_STK:
       tlbl=newiTempLabel(NULL);
-      emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
-      emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
-      if (*AOP_NAME(cond)[1]) {
-       emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
-       emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
+      if (AOP_SIZE(cond)==1) {
+       instr="cmp.b";
+      } else {
+       instr="cmp.w";
+      }
+      emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
+      emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
+      if (AOP_SIZE(cond) > 2) {
+       if (AOP_SIZE(cond)==3) {
+         instr="cmp.b";
+       } else {
+         instr="cmp.w";
+       }
+       emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
+       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
       }
       emitcode ("jmp", "%05d$", jlbl->key+100);
       emitcode ("", "%05d$:", tlbl->key+100);
       return;
     }
+  bailOut ("genIfx");
 }
 
 /*-----------------------------------------------------------------*/
 /* genAddrOf - generates code for address of                       */
 /*-----------------------------------------------------------------*/
 static void genAddrOf (iCode * ic) {
+  operand *left=IC_LEFT(ic);
+
   printIc ("genAddrOf", ic, 1,1,0);
+
+  aopOp (IC_RESULT(ic),TRUE);
+
+  if (isOperandOnStack(left)) {
+    emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
+             getStackOffset(OP_SYMBOL(left)->stack));
+    if (AOP_SIZE(IC_RESULT(ic)) > 2) {
+      // this must be a generic pointer
+      emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
+    }
+    return;
+  }
+
+  if (isOperandInDirSpace(left) ||
+      isOperandInFarSpace(left) ||
+      isOperandInCodeSpace(left)) {
+    emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
+             OP_SYMBOL(left));
+    if (AOP_SIZE(IC_RESULT(ic)) > 2) {
+      // this must be a generic pointer
+      int space=0; // dir space
+      if (isOperandInFarSpace(left)) {
+       space=1;
+      } else if (isOperandInCodeSpace(left)) {
+       space=2;
+      }
+      emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
+    }
+    return;
+  }
+
+  bailOut("genAddrOf");
 }
 
 /*-----------------------------------------------------------------*/
@@ -881,20 +1173,23 @@ static void genAddrOf (iCode * ic) {
 /*-----------------------------------------------------------------*/
 static void genAssign (iCode * ic) {
   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
+  int size;
+  char *instr;
 
   printIc ("genAssign", ic, 1,0,1);
   
   if (!IS_SYMOP(result)) {
-    fprintf (stderr, "genAssign: result is not a symbol\n");
-    exit (1);
+    bailOut("genAssign: result is not a symbol");
   }
   
   aopOp(right, FALSE);
   aopOp(result, TRUE);
+  size=AOP_SIZE(result);
 
   if (result->aop->type==AOP_REG || 
       right->aop->type==AOP_REG ||
       right->aop->type==AOP_LIT ||
+      right->aop->type==AOP_STK ||
       right->aop->type==AOP_IMMD) {
     // everything will do
   } else {
@@ -929,10 +1224,20 @@ static void genAssign (iCode * ic) {
   }
 
   /* general case */
-  emitcode ("mov", "%s,%s", 
+  if (size==1) {
+    instr=MOVB;
+  } else {
+    instr=MOVW;
+  }
+  emitcode (instr, "%s,%s",
            result->aop->name[0], right->aop->name[0]);
-  if (IS_GENPTR(operandType(result))) {
-    emitcode ("mov", "%s,%s",
+  if (AOP_SIZE(result) > 2) {
+    if (size==3) {
+      instr=MOVB;
+    } else {
+      instr=MOVW;
+    }
+    emitcode (instr, "%s,%s",
              result->aop->name[1], right->aop->name[1]);
   }
   
@@ -956,8 +1261,48 @@ static void genCast (iCode * ic) {
 /* genDjnz - generate decrement & jump if not zero instrucion      */
 /*-----------------------------------------------------------------*/
 static bool genDjnz (iCode * ic, iCode * ifx) {
-  printIc ("genDjnz", ic, 0,0,0);
-  return FALSE;
+  symbol *lbl, *lbl1;
+
+  if (!ifx)
+    return 0;
+
+  /* if the if condition has a false label
+     then we cannot save */
+  if (IC_FALSE (ifx))
+    return 0;
+
+  /* if the minus is not of the form
+     a = a - 1 */
+  if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
+      !IS_OP_LITERAL (IC_RIGHT (ic)))
+    return 0;
+
+  if (operandLitValue (IC_RIGHT (ic)) != 1)
+    return 0;
+
+  /* if the size of this greater than two then no
+     saving */
+  if (getSize (operandType (IC_RESULT (ic))) > 2)
+    return 0;
+
+  printIc ("genDjnz", ic, 1,1,1);
+
+  /* otherwise we can save BIG */
+  lbl = newiTempLabel (NULL);
+  lbl1 = newiTempLabel (NULL);
+
+  aopOp (IC_RESULT (ic), TRUE);
+
+  if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
+    emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
+    emitcode ("bra", "%05d$", lbl1->key + 100);
+    emitcode ("", "%05d$:", lbl->key + 100);
+    emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
+    emitcode ("", "%05d$:", lbl1->key + 100);
+    return TRUE;
+  }
+    bailOut("genDjnz: aop type");
+    return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1002,7 +1347,8 @@ void genXA51Code (iCode * lic) {
                  ic->level, ic->block);
        _G.debugLine = 0;
       }
-      emitcode (";", "%s %d", ic->filename, ic->lineno);
+      emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
+               printCLine(ic->filename, ic->lineno));
       cln = ic->lineno;
     }
     /* if the result is marked as
@@ -1096,25 +1442,27 @@ void genXA51Code (iCode * lic) {
        break;
        
       case '>':
-       genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+       genCmpGt (ic);
        break;
        
       case '<':
-       genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+       genCmpLt (ic);
        break;
        
       case LE_OP:
+       genCmpLe (ic);
+       break;
+
       case GE_OP:
+       genCmpGe (ic);
+       break;
+
       case NE_OP:
-       
-       /* note these two are xlated by algebraic equivalence
-          during parsing SDCC.y */
-       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-               "got '>=' or '<=' shouldn't have come here");
+       genCmpNe (ic);
        break;
-       
+
       case EQ_OP:
-       genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+       genCmpEq (ic);
        break;
        
       case AND_OP: