8a5a2b16bc54c24d1758e5d1423cc188c305f803
[fw/sdcc] / src / xa51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26 -------------------------------------------------------------------------*/
27
28 //#define D(x)
29 #define D(x) x
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #include "common.h"
39 #include "SDCCpeeph.h"
40 #include "ralloc.h"
41 #include "gen.h"
42
43 #if defined(__BORLANDC__) || defined(_MSC_VER)
44 #define STRCASECMP stricmp
45 #else
46 #define STRCASECMP strcasecmp
47 #endif
48
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static struct
57   {
58     short inLine;
59     short debugLine;
60     short stackExtend;
61     short nRegsSaved;
62     short parmsPushed;
63     set *sendSet;
64   }
65 _G;
66
67 extern int xa51_ptrRegReq;
68 extern int xa51_nRegs;
69 extern FILE *codeOutFile;
70
71 static lineNode *lineHead = NULL;
72 static lineNode *lineCurr = NULL;
73
74 #define LSB     0
75 #define MSB16   1
76 #define MSB24   2
77 #define MSB32   3
78
79 static char *MOV="mov";
80 static char *MOVB="mov.b";
81 static char *MOVW="mov.w";
82 static char *MOVC="movc";
83 static char *MOVCB="movc.b";
84 static char *MOVCW="movc.w";
85
86 static char *R1L="r1l";
87 static char *R1="r1";
88
89 void bailOut (char *mesg) {
90   fprintf (stderr, "%s: bailing out\n", mesg);
91   exit (1);
92 }
93
94 /*-----------------------------------------------------------------*/
95 /* emitcode - writes the code into a file : for now it is simple    */
96 /*-----------------------------------------------------------------*/
97 static void emitcode (char *inst, char *fmt,...) {
98   va_list ap;
99   char lb[INITIAL_INLINEASM];
100   char *lbp = lb;
101
102   va_start (ap, fmt);
103
104   if (inst && *inst)
105     {
106       if (fmt && *fmt)
107         sprintf (lb, "%s\t", inst);
108       else
109         sprintf (lb, "%s", inst);
110       vsprintf (lb + (strlen (lb)), fmt, ap);
111     }
112   else
113     vsprintf (lb, fmt, ap);
114
115   while (isspace ((int)*lbp))
116     lbp++;
117
118   if (lbp && *lbp)
119     lineCurr = (lineCurr ?
120                 connectLine (lineCurr, newLineNode (lb)) :
121                 (lineHead = newLineNode (lb)));
122   lineCurr->isInline = _G.inLine;
123   lineCurr->isDebug = _G.debugLine;
124   va_end (ap);
125 }
126
127 char *getStackOffset(int stack) {
128   static char gsoBuf[1024];
129   sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
130            currFunc->stack, _G.nRegsSaved);
131   return gsoBuf;
132 }
133
134 /*-----------------------------------------------------------------*/
135 /* newAsmop - creates a new asmOp                                  */
136 /*-----------------------------------------------------------------*/
137 static asmop *
138 newAsmop (short type)
139 {
140   asmop *aop;
141
142   aop = Safe_calloc (1, sizeof (asmop));
143   aop->type = type;
144   return aop;
145 }
146
147 char *aopTypeName(asmop *aop) {
148   switch (aop->type)
149     {
150     case AOP_LIT: return "lit";
151     case AOP_REG: return "reg";
152     case AOP_DIR: return "dir";
153     case AOP_FAR: return "far";
154     case AOP_CODE: return "code";
155     case AOP_GPTR: return "gptr";
156     case AOP_STK: return "stack";
157     case AOP_IMMD: return "imm";
158     case AOP_BIT: return "bit";
159     }
160   return "unknown";
161 }
162
163 /*-----------------------------------------------------------------*/
164 /* aopForSym - for a true symbol                                   */
165 /*-----------------------------------------------------------------*/
166 static asmop *aopForSym(symbol *sym, 
167                         bool canUsePointer, bool canUseOffset) {
168   int size;
169   asmop *aop;
170
171   sym->aop = aop = newAsmop(0);
172   size=aop->size=getSize(sym->type);
173
174   // if the sym has registers
175   if (sym->nRegs && sym->regs[0]) {
176     aop->type=AOP_REG;
177     sprintf (aop->name[0], sym->regs[0]->name);
178     if (size > 2) {
179       sprintf (aop->name[1], sym->regs[1]->name);
180     }
181     return aop;
182   }
183
184   // if it is on stack
185   if (sym->onStack) {
186     if (!canUsePointer || !canUseOffset) {
187       aop->type=AOP_REG;
188       switch (size) 
189         {
190         case 1:
191           emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack));
192           sprintf (aop->name[0], "r0l");
193           return aop;
194         case 2:
195           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
196           sprintf (aop->name[0], "r0");
197           return aop;
198         case 3:
199           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
200           sprintf (aop->name[0], "r0");
201           emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
202           sprintf (aop->name[1], "r1l");
203           return aop;
204         case 4:
205           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
206           sprintf (aop->name[0], "r0");
207           emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2));
208           sprintf (aop->name[1], "r1");
209           return aop;
210         }
211     }
212     aop->type=AOP_STK;
213     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
214     if (size > 2) {
215       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
216     }
217     return aop;
218   }
219
220   // if it has a spillLoc
221   if (sym->usl.spillLoc) {
222     return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
223   }
224
225   // if in bit space
226   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
227     aop->type=AOP_BIT;
228     sprintf (aop->name[0], sym->rname);
229     return aop;
230   }
231
232   // if in direct space
233   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
234     aop->type=AOP_DIR;
235     sprintf (aop->name[0], sym->rname);
236     if (size>2) {
237       sprintf (aop->name[1], "%s+2", sym->rname);
238     }
239     return aop;
240   }
241
242   // if in code space
243   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
244     if (!canUsePointer) {
245       aop->type=AOP_REG;
246       switch (size) 
247         {
248         case 1:
249           emitcode (MOV, "r0,#%s", sym->rname);
250           emitcode (MOVC, "r0l,[r0+]");
251           sprintf (aop->name[0], "r0l");
252           return aop;
253         case 2:
254           emitcode (MOV, "r0,#%s", sym->rname);
255           emitcode (MOVC, "r0,[r0+]");
256           sprintf (aop->name[0], "r0");
257           return aop;
258         case 3:
259           emitcode (MOV, "r0,#%s", sym->rname);
260           emitcode (MOVC, "r0,[r0+]");
261           sprintf (aop->name[1], "r0");
262           emitcode (MOV, "r1l,[r0+]");
263           sprintf (aop->name[0], "r1l");
264           return aop;
265         case 4:
266           emitcode (MOV, "r0,#%s", sym->rname);
267           emitcode (MOVC, "r1,[r0+]");
268           emitcode (MOVC, "r0,[r0+]");
269           emitcode ("xch", "r0,r1");
270           sprintf (aop->name[0], "r0");
271           sprintf (aop->name[1], "r1");
272           return aop;
273         }
274       
275     } else {
276       aop->type=AOP_CODE;
277       emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
278       sprintf (aop->name[0], "[r0]");
279       if (size>2) {
280         sprintf (aop->name[1], "[r0+2]");
281       }
282     }
283     return aop;
284   }
285
286   // if in far space
287   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
288     if (!canUsePointer) {
289       aop->type=AOP_REG;
290       switch (size) 
291         {
292         case 1:
293           emitcode (MOV, "r0,#%s", sym->rname);
294           emitcode (MOV, "r0l,[r0]");
295           sprintf (aop->name[0], "r0l");
296           return aop;
297         case 2:
298           emitcode (MOV, "r0,#%s", sym->rname);
299           emitcode (MOV, "r0,[r0]");
300           sprintf (aop->name[0], "r0");
301           return aop;
302         case 3:
303           emitcode (MOV, "r0,#%s", sym->rname);
304           emitcode (MOV, "r1l,[r0+2]");
305           sprintf (aop->name[1], "r1l");
306           emitcode (MOV, "r0,[r0]");
307           sprintf (aop->name[0], "r0");
308           return aop;
309         case 4:
310           emitcode (MOV, "r0,#%s", sym->rname);
311           emitcode (MOV, "r1,[r0+2]");
312           sprintf (aop->name[1], "r1");
313           emitcode (MOV, "r0,[r0]");
314           sprintf (aop->name[0], "r0");
315           return aop;
316         }
317     } else {
318       aop->type=AOP_FAR;
319       emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
320       sprintf (aop->name[0], "[r0]");
321       if (size>2) {
322         sprintf (aop->name[1], "[r0+2]");
323       }
324       return aop;
325     }
326   }
327   
328   bailOut("aopForSym");
329   return NULL;
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* aopForVal - for a value                                         */
334 /*-----------------------------------------------------------------*/
335 static asmop *aopForVal(operand *op) {
336   asmop *aop;
337
338   if (IS_OP_LITERAL(op)) {
339     op->aop = aop = newAsmop (AOP_LIT);
340     switch ((aop->size=getSize(operandType(op))))
341       {
342       case 1:
343         sprintf (aop->name[0], "#0x%02x", 
344                  SPEC_CVAL(operandType(op)).v_int & 0xff);
345         sprintf (aop->name[1], "#0");
346         break;
347       case 2:
348         sprintf (aop->name[0], "#0x%04x", 
349                  SPEC_CVAL(operandType(op)).v_int & 0xffff);
350         sprintf (aop->name[1], "#0");
351         break;
352       case 3:
353         // must be a generic pointer, can only be zero
354         // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
355         sprintf (aop->name[0], "#0x%04x", 
356                  SPEC_CVAL(operandType(op)).v_uint & 0xffff);
357         sprintf (aop->name[1], "#0");
358         break;
359       case 4:
360         sprintf (aop->name[0], "#0x%04x",
361                  SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
362         sprintf (aop->name[1], "#0x%04x", 
363                  SPEC_CVAL(operandType(op)).v_ulong >> 16);
364         break;
365       default:
366         bailOut("aopForVal");
367       }
368     return aop;
369   }
370
371   // must be immediate
372   if (IS_SYMOP(op)) {
373     op->aop = aop = newAsmop (AOP_IMMD);
374     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
375       {
376       case 1:
377       case 2:
378         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
379         return aop;
380       case 3: // generic pointer
381         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
382         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
383         return aop;
384       }
385   }
386
387   bailOut ("aopForVal: unknown type");
388   return NULL;
389 }
390
391 static int aopOp(operand *op, 
392                   bool canUsePointer, bool canUseOffset) {
393
394   if (IS_SYMOP(op)) {
395     op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
396     return AOP_SIZE(op);
397   }
398   if (IS_VALOP(op)) {
399     op->aop=aopForVal (op);
400     return AOP_SIZE(op);
401   }
402
403   bailOut("aopOp: unexpected operand");
404   return 0;
405 }
406
407 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
408   if (strcmp(aop1->name[offset], aop2->name[offset])) {
409     return FALSE;
410   }
411   return TRUE;
412 }
413
414 bool aopIsDir(operand *op) {
415   return AOP_TYPE(op)==AOP_DIR;
416 }
417
418 bool aopIsBit(operand *op) {
419   return AOP_TYPE(op)==AOP_BIT;
420 }
421
422 bool aopIsPtr(operand *op) {
423   if (AOP_TYPE(op)==AOP_STK ||
424       AOP_TYPE(op)==AOP_CODE ||
425       AOP_TYPE(op)==AOP_FAR) {
426     return TRUE;
427   } else {
428     return FALSE;
429   }
430 }
431       
432 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
433
434   if (IS_SYMOP(op)) {
435     if (OP_SYMBOL(op)->onStack) {
436       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
437       return opName;
438     }
439     if (IS_TRUE_SYMOP(op))
440       return OP_SYMBOL(op)->rname;
441     else if (OP_SYMBOL(op)->regs[offset])
442       return OP_SYMBOL(op)->regs[offset]->name;
443     else
444       bailOut("opRegName: unknown regs");
445   }
446
447   if (IS_VALOP(op)) {
448     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
449     case V_SBIT:
450     case V_BIT:
451       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
452           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
453         bailOut("opRegName: invalid bit value");
454       }
455       // fall through
456     case V_CHAR:
457       sprintf (opName, "#%s0x%02x", decorate?"(char)":"", 
458                SPEC_CVAL(OP_VALUE(op)->type).v_int);
459       break;
460     case V_INT:
461       if (SPEC_LONG(OP_VALUE(op)->type)) {
462         sprintf (opName, "#%s0x%02x", decorate?"(long)":"",
463                  SPEC_CVAL(OP_VALUE(op)->type).v_long);
464       } else {
465         sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
466                  SPEC_CVAL(OP_VALUE(op)->type).v_int);
467       }
468       break;
469     case V_FLOAT:
470       sprintf (opName, "#%s%f", decorate?"(float)":"",
471                SPEC_CVAL(OP_VALUE(op)->type).v_float);
472       break;
473     default: 
474       bailOut("opRegName: unexpected noun");
475     }
476     return opName;
477   }
478   bailOut("opRegName: unexpected operand type");
479   return NULL;
480 }
481
482 char * printOp (operand *op) {
483   static char line[132];
484   sym_link *optype=operandType(op);
485   bool isPtr = IS_PTR(optype);
486
487   if (IS_SYMOP(op)) {
488     symbol *sym=OP_SYMBOL(op);
489     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
490       sym=SYM_SPIL_LOC(sym);
491     }
492     if (isPtr) {
493       sprintf (line, "[");
494       if (DCL_TYPE(optype)==FPOINTER)
495         strcat (line, "far * ");
496       else if (DCL_TYPE(optype)==CPOINTER)
497         strcat (line, "code * ");
498       else if (DCL_TYPE(optype)==GPOINTER)
499         strcat (line, "gen * ");
500       else if (DCL_TYPE(optype)==POINTER)
501         strcat (line, "near * ");
502       else
503         strcat (line, "unknown * ");
504       strcat (line, "(");
505       strcat (line, nounName(sym->etype));
506       strcat (line, ")");
507       strcat (line, sym->name);
508       strcat (line, "]:");
509     } else {
510       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
511     }
512     if (sym->regs[0]) {
513       strcat (line, sym->regs[0]->name);
514       if (sym->regs[1]) {
515         strcat (line, ",");
516         strcat (line, sym->regs[1]->name);
517       }
518       return line;
519     }
520     if (sym->onStack) {
521       sprintf (line+strlen(line), "stack%+d", sym->stack);
522       return line;
523     }
524     if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
525       strcat (line, "code");
526       return line;
527     }
528     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
529       strcat (line, "far");
530       return line;
531     }
532     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
533       strcat (line, "bit");
534       return line;
535     }
536     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
537       strcat (line, "dir");
538       return line;
539     }
540     strcat (line, "unknown");
541     return line;
542   } else if (IS_VALOP(op)) {
543     opRegName(op, 0, line, 1);
544   } else if (IS_TYPOP(op)) {
545     sprintf (line, "(");
546     if (isPtr) {
547       if (DCL_TYPE(optype)==FPOINTER)
548         strcat (line, "far * ");
549       else if (DCL_TYPE(optype)==CPOINTER)
550         strcat (line, "code * ");
551       else if (DCL_TYPE(optype)==GPOINTER)
552         strcat (line, "gen * ");
553       else if (DCL_TYPE(optype)==POINTER)
554         strcat (line, "near * ");
555       else
556         strcat (line, "unknown * ");
557     }
558     // forget about static, volatile, ... for now
559     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
560     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
561     strcat (line, nounName(operandType(op)));
562     strcat (line, ")");
563   } else {
564     bailOut("printOp: unexpected operand type");
565   }
566   return line;
567 }
568
569 void printIc (bool printToStderr, 
570               char *op, iCode * ic, bool result, bool left, bool right) {
571   char line[132];
572
573   sprintf (line, "%s(%d)", op, ic->lineno);
574   if (result) {
575     strcat (line, " result=");
576     strcat (line, printOp (IC_RESULT(ic)));
577   }
578   if (left) {
579     strcat (line, " left=");
580     strcat (line, printOp (IC_LEFT(ic)));
581   }
582   if (right) {
583     strcat (line, " right=");
584     strcat (line, printOp (IC_RIGHT(ic)));
585   }
586   emitcode (";", line);
587   if (printToStderr) {
588     fprintf (stderr, "%s\n", line);
589   }
590 }
591
592 /*-----------------------------------------------------------------*/
593 /* toBoolean - return carry for operand!=0                           */
594 /*-----------------------------------------------------------------*/
595 static char *toBoolean (operand * op) {
596   symbol *tlbl=newiTempLabel(NULL);
597
598   switch (AOP_SIZE(op)) 
599     {
600     case 1:
601     case 2:
602       emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
603                 "This needs a second thought");
604       
605       emitcode ("", "%05d$:", tlbl->key+100);
606       return "c";
607     }
608
609   bailOut("toBoolean: unknown size");
610   return NULL;
611 }
612
613 /*-----------------------------------------------------------------*/
614 /* regsInCommon - two operands have some registers in common       */
615 /*-----------------------------------------------------------------*/
616 static bool regsInCommon (operand * op1, operand * op2) {
617   symbol *sym1, *sym2;
618   int i;
619
620   /* if they have registers in common */
621   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
622     return FALSE;
623
624   sym1 = OP_SYMBOL (op1);
625   sym2 = OP_SYMBOL (op2);
626
627   if (sym1->nRegs == 0 || sym2->nRegs == 0)
628     return FALSE;
629
630   for (i = 0; i < sym1->nRegs; i++)
631     {
632       int j;
633       if (!sym1->regs[i])
634         continue;
635
636       for (j = 0; j < sym2->nRegs; j++)
637         {
638           if (!sym2->regs[j])
639             continue;
640
641           if (sym2->regs[j] == sym1->regs[i])
642             return TRUE;
643         }
644     }
645
646   return FALSE;
647 }
648
649 /*-----------------------------------------------------------------*/
650 /* resultRemat - result  is rematerializable                       */
651 /*-----------------------------------------------------------------*/
652 static int resultRemat (iCode * ic) {
653   if (SKIP_IC (ic) || ic->op == IFX)
654     return 0;
655   
656   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
657     {
658       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
659       if (sym->remat && !POINTER_SET (ic))
660         return 1;
661     }
662   
663   return 0;
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* genNot - generate code for ! operation                          */
668 /*-----------------------------------------------------------------*/
669 static void genNot (iCode * ic) {
670   printIc (0, "genNot:", ic, 1,1,0);
671 }
672
673 /*-----------------------------------------------------------------*/
674 /* genCpl - generate code for complement                           */
675 /*-----------------------------------------------------------------*/
676 static void genCpl (iCode * ic) {
677   printIc (0, "genCpl", ic, 1,1,0);
678 }
679
680 /*-----------------------------------------------------------------*/
681 /* genUminus - unary minus code generation                         */
682 /*-----------------------------------------------------------------*/
683 static void genUminus (iCode * ic) {
684   printIc (0, "genUminus", ic, 1,1,0);
685 }
686
687 /*-----------------------------------------------------------------*/
688 /* genIpush - generate code for pushing                            */
689 /*-----------------------------------------------------------------*/
690 static void genIpush (iCode * ic) {
691   operand *left=IC_LEFT(ic);
692
693   printIc (0, "genIpush", ic, 0,1,0);
694   aopOp(left,FALSE,FALSE);
695
696
697   if (AOP_TYPE(left)==AOP_LIT) {
698     switch (AOP_SIZE(left)) 
699       {
700       case 1:
701         emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
702         emitcode ("push", "r1l");
703         _G.parmsPushed++;
704         return;
705       case 2:
706         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
707         emitcode ("push", "r1");
708         _G.parmsPushed++;
709         return;
710       case 3:
711         emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
712         emitcode ("push", "r1l");
713         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
714         emitcode ("push", "r1");
715         _G.parmsPushed += 2;
716         return;
717       case 4:
718         emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
719         emitcode ("push", "r1");
720         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
721         emitcode ("push", "r1");
722         _G.parmsPushed += 2;
723         return;
724       }
725   } else {
726     if (AOP_SIZE(left)>2) {
727       emitcode ("push", "%s", AOP_NAME(left)[1]);
728       _G.parmsPushed++;
729     }
730     emitcode ("push", "%s", AOP_NAME(left)[0]);
731     _G.parmsPushed++;
732   }
733 }
734
735 /*-----------------------------------------------------------------*/
736 /* genIpop - recover the registers: can happen only for spilling   */
737 /*-----------------------------------------------------------------*/
738 static void genIpop (iCode * ic) {
739   printIc (0, "genIpop", ic, 0,1,0);
740 }
741
742 /*-----------------------------------------------------------------*/
743 /* genCall - generates a call statement                            */
744 /*-----------------------------------------------------------------*/
745 static void genCall (iCode * ic) {
746   operand *result=IC_RESULT(ic);
747
748   emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
749             OP_SYMBOL(IC_LEFT(ic))->name,
750             printOp (IC_RESULT(ic)));
751   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
752
753   /* readjust the stack if we have pushed some parms */
754   if (_G.parmsPushed) {
755     emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
756     _G.parmsPushed=0;
757   }
758
759   /* if we need to assign a result value */
760   if (IS_ITEMP (IC_RESULT(ic)) &&
761       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
762     aopOp(result,FALSE,FALSE);
763     switch (AOP_SIZE(result))
764       {
765       case 1:
766         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
767         return;
768       case 2:
769         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
770         return;
771       case 3:
772         // generic pointer
773         emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
774         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
775         return;
776       case 4:
777         emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
778         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
779         return;
780       }
781     bailOut("genCall");
782   }
783 }
784
785 /*-----------------------------------------------------------------*/
786 /* genPcall - generates a call by pointer statement                */
787 /*-----------------------------------------------------------------*/
788 static void
789 genPcall (iCode * ic)
790 {
791   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
792 }
793
794 /*-----------------------------------------------------------------*/
795 /* genFunction - generated code for function entry                 */
796 /*-----------------------------------------------------------------*/
797 static void genFunction (iCode * ic) {
798   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
799   sym_link *type=sym->type;
800
801   emitcode (";", "genFunction %s", sym->rname);
802
803   /* print the allocation information */
804   printAllocInfo (currFunc, codeOutFile);
805
806   emitcode ("", "%s:", sym->rname);
807
808   if (IFFUNC_ISNAKED(type))
809   {
810       emitcode(";", "naked function: no prologue.");
811       return;
812   }
813
814   /* adjust the stack for locals used in this function */
815   if (sym->stack) {
816     emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
817   }
818 }
819
820 /*-----------------------------------------------------------------*/
821 /* genEndFunction - generates epilogue for functions               */
822 /*-----------------------------------------------------------------*/
823 static void
824 genEndFunction (iCode * ic)
825 {
826   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
827
828   printIc (0, "genEndFunction", ic, 0,0,0);
829
830   if (IFFUNC_ISNAKED(sym->type)) {
831       emitcode(";", "naked function: no epilogue.");
832       return;
833   }
834
835   /* readjust the stock for locals used in this function */
836   if (sym->stack) {
837     emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
838   }
839
840   if (IFFUNC_ISISR(sym->type)) {
841     emitcode ("reti", "");
842   } else {
843     emitcode ("ret", "");
844   }
845 }
846
847 /*-----------------------------------------------------------------*/
848 /* genRet - generate code for return statement                     */
849 /*-----------------------------------------------------------------*/
850 static void genRet (iCode * ic) {
851
852   if (!IC_LEFT(ic)) {
853     printIc (0, "genRet", ic, 0, 0, 0);
854   } else {
855     printIc (0, "genRet", ic, 0, 1, 0);
856     aopOp(IC_LEFT(ic), TRUE, TRUE);
857     switch (AOP_SIZE(IC_LEFT(ic)))
858       {
859       case 4:
860         emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
861         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
862         break;
863       case 3:
864         emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
865         // fall through
866       case 2:
867         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
868         break;
869       case 1:
870         emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
871         break;
872       default:
873         bailOut("genRet");
874       }
875   }
876
877   emitcode ("jmp", "%05d$", returnLabel->key+100);
878 }
879
880 /*-----------------------------------------------------------------*/
881 /* genLabel - generates a label                                    */
882 /*-----------------------------------------------------------------*/
883 static void genLabel (iCode * ic) {
884   /* special case never generate */
885   if (IC_LABEL (ic) == entryLabel)
886     return;
887
888   emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
889   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
890 }
891
892 /*-----------------------------------------------------------------*/
893 /* genGoto - generates a jmp                                      */
894 /*-----------------------------------------------------------------*/
895 static void genGoto (iCode * ic) {
896   emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
897   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* genPlus - generates code for addition                           */
902 /*-----------------------------------------------------------------*/
903 static void genPlus (iCode * ic) {
904   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
905   int size;
906   char *instr;
907
908   printIc (0, "genPlus", ic, 1,1,1);
909
910   size=aopOp(result, TRUE, TRUE);
911
912   /* if left is a literal, then exchange them */
913   if (IS_LITERAL(operandType(left))) {
914     operand *tmp = right;
915     right = left;
916     left = tmp;
917   }
918     
919   if (aopIsBit(result)) {
920     if (IS_LITERAL(operandType(right))) {
921       if (operandLitValue(right)) {
922         emitcode ("setb", AOP_NAME(result)[0]);
923         return;
924       }
925       aopOp(left, TRUE, TRUE);
926       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
927       return;
928     }
929     bailOut("genPlus: unfinished genPlus bit");
930   }
931   
932   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
933   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
934
935   // special case for "* = * + char", needs a closer look
936   // heck, this shouldn't have come here but bug-223113 does
937   if (size==3 && AOP_SIZE(right)==1) {
938     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
939     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
940     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
941     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
942     emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
943     return;
944   }
945
946   // special case for "xdata * = xdata * + char", needs a closer look
947   // heck, this shouldn't have come here but bug-441448 does
948   if (size==2 && AOP_SIZE(right)==1) {
949     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
950     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
951     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
952     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
953     return;
954   }
955
956   if (size>1) {
957     instr="add.w";
958   } else {
959     instr="add.b";
960   }
961   if (!aopEqual(result->aop, left->aop, 0)) {
962     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
963   }
964   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
965   if (size>2) {
966     if (!aopEqual(result->aop, left->aop, 1)) {
967       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
968     }
969     if (size==3) {
970       // generic pointer
971     } else {
972       emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
973     }
974   }
975   return;
976 }
977
978 /*-----------------------------------------------------------------*/
979 /* genMinus - generates code for subtraction                       */
980 /*-----------------------------------------------------------------*/
981 static void genMinus (iCode * ic) {
982   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
983   int size;
984   char *instr;
985
986   printIc (0, "genMinus", ic, 1,1,1);
987
988   size=aopOp(result, TRUE, TRUE);
989
990   /* if left is a literal, then exchange them */
991   if (IS_LITERAL(operandType(left))) {
992     operand *tmp = right;
993     right = left;
994     left = tmp;
995   }
996     
997   if (aopIsBit(result)) {
998     if (IS_LITERAL(operandType(right))) {
999       if (operandLitValue(right)) {
1000         emitcode ("clr", AOP_NAME(result)[0]);
1001         return;
1002       }
1003       aopOp(left, TRUE, TRUE);
1004       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1005       return;
1006     }
1007     bailOut("genPlus: unfinished genPlus bit");
1008   }
1009   
1010   if (isOperandEqual(result,left)) {
1011     left->aop=result->aop;
1012   } else {
1013     aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1014   }
1015   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1016
1017   if (size>1) {
1018     instr="sub.w";
1019   } else {
1020     instr="sub.b";
1021   }
1022   if (!aopEqual(result->aop, left->aop, 0)) {
1023     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1024   }
1025   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1026   if (size>2) {
1027     if (!aopEqual(result->aop, left->aop, 1)) {
1028       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1029     }
1030     if (size==3) {
1031       // generic pointer
1032     } else {
1033       emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1034     }
1035   }
1036   return;
1037 }
1038
1039 /*-----------------------------------------------------------------*/
1040 /* genMult - generates code for multiplication                     */
1041 /*-----------------------------------------------------------------*/
1042 static void genMult (iCode * ic) {
1043   printIc (0, "genMult", ic, 1,1,1);
1044 }
1045
1046 /*-----------------------------------------------------------------*/
1047 /* genDiv - generates code for division                            */
1048 /*-----------------------------------------------------------------*/
1049 static void genDiv (iCode * ic) {
1050   printIc (0, "genDiv", ic, 1,1,1);
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* genMod - generates code for division                            */
1055 /*-----------------------------------------------------------------*/
1056 static void genMod (iCode * ic) {
1057   printIc (0, "genMod", ic, 1,1,1);
1058 }
1059
1060 /*-----------------------------------------------------------------*/
1061 /* ifxForOp - returns the icode containing the ifx for operand     */
1062 /*-----------------------------------------------------------------*/
1063 static iCode *ifxForOp (operand * op, iCode * ic) {
1064   /* if true symbol then needs to be assigned */
1065   if (IS_TRUE_SYMOP (op))
1066     return NULL;
1067   
1068   /* if this has register type condition and
1069      the next instruction is ifx with the same operand
1070      and live to of the operand is upto the ifx only then */
1071   if (ic->next &&
1072       ic->next->op == IFX &&
1073       IC_COND (ic->next)->key == op->key &&
1074       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1075     return ic->next;
1076   
1077   return NULL;
1078 }
1079
1080 /*-----------------------------------------------------------------*/
1081 /* genCmp - compares whatever                                      */
1082 /*-----------------------------------------------------------------*/
1083 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1084   iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1085   operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1086   int size;
1087   bool isTrue;
1088   char *instr;
1089   int jlbl;
1090
1091
1092   size=aopOp(left, TRUE, TRUE);
1093   aopOp(right, !aopIsPtr(left), TRUE);
1094
1095   if (size==1) {
1096     instr="cmp.b";
1097   } else {
1098     instr="cmp.w";
1099   }
1100
1101   if (IC_TRUE(ifx)) {
1102     isTrue=TRUE;
1103     jlbl=IC_TRUE(ifx)->key+100;
1104   } else {
1105     isTrue=FALSE;
1106     jlbl=IC_FALSE(ifx)->key+100;
1107   }
1108   
1109   if (!ifx) {
1110     aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1111     jlbl=newiTempLabel(NULL)->key+100;
1112     emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1113     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1114     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1115     emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1116     emitcode("", "%05d$:", jlbl);
1117   } else {
1118     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1119     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1120     ifx->generated=1;
1121   }
1122
1123   if (size>2) {
1124     bailOut("genCmp: size > 2");
1125   }
1126
1127 }
1128
1129 /*-----------------------------------------------------------------*/
1130 /* genCmpEq :- generates code for equal to                         */
1131 /*-----------------------------------------------------------------*/
1132 static void genCmpEq (iCode * ic) {
1133   printIc (0, "genCmpEq", ic, 0,1,1);
1134   genCmp(ic, "beq", "bne"); // no sign
1135 }
1136
1137 /*-----------------------------------------------------------------*/
1138 /* genCmpGt :- greater than comparison                             */
1139 /*-----------------------------------------------------------------*/
1140 static void genCmpGt (iCode * ic) {
1141   printIc (0, "genCmpGt", ic, 0,1,1);
1142   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1143       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1144     genCmp(ic, "bg", "bl"); // unsigned
1145   } else {
1146     genCmp(ic, "bgt", "ble"); // signed
1147   }
1148 }
1149
1150 /*-----------------------------------------------------------------*/
1151 /* genCmpLt - less than comparisons                                */
1152 /*-----------------------------------------------------------------*/
1153 static void genCmpLt (iCode * ic) {
1154   printIc (0, "genCmpLt", ic, 0,1,1);
1155   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1156       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1157     genCmp(ic, "bcs", "bcc"); // unsigned
1158   } else {
1159     genCmp(ic, "blt", "bge"); // signed
1160   }
1161 }
1162
1163 /*-----------------------------------------------------------------*/
1164 /* hasInc - operand is incremented before any other use            */
1165 /*-----------------------------------------------------------------*/
1166 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1167   sym_link *type = operandType(op);
1168   sym_link *retype = getSpec (type);
1169   iCode *lic = ic->next;
1170   int isize ;
1171   
1172   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1173   if (!IS_SYMOP(op)) return NULL;
1174
1175   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1176   if (IS_AGGREGATE(type->next)) return NULL;
1177   if (osize != (isize = getSize(type->next))) return NULL;
1178
1179   while (lic) {
1180     /* if operand of the form op = op + <sizeof *op> */
1181     if (lic->op == '+') {
1182       if (isOperandEqual(IC_LEFT(lic),op) &&
1183           //isOperandEqual(IC_RESULT(lic),op) && 
1184           isOperandLiteral(IC_RIGHT(lic)) &&
1185           operandLitValue(IC_RIGHT(lic)) == isize) {
1186         emitcode (";", "Found hasInc");
1187         return lic;
1188       }
1189     }
1190     /* if the operand used or deffed */
1191     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1192       return NULL;
1193     }
1194     /* if GOTO or IFX */
1195     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1196     lic = lic->next;
1197   }
1198   return NULL;
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* genAndOp - for && operation                                     */
1203 /*-----------------------------------------------------------------*/
1204 static void genAndOp (iCode * ic) {
1205   printIc (0, "genAndOp(&&)", ic, 1,1,1);
1206 }
1207
1208 /*-----------------------------------------------------------------*/
1209 /* genOrOp - for || operation                                      */
1210 /*-----------------------------------------------------------------*/
1211 static void genOrOp (iCode * ic) {
1212   printIc (0, "genOrOp(||)", ic, 1,1,1);
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* genAnd  - code for and                                            */
1217 /*-----------------------------------------------------------------*/
1218 static void genAnd (iCode * ic, iCode * ifx) {
1219   printIc (0, "genAnd", ic, 1,1,1);
1220 }
1221
1222 /*-----------------------------------------------------------------*/
1223 /* genOr  - code for or                                            */
1224 /*-----------------------------------------------------------------*/
1225 static void genOr (iCode * ic, iCode * ifx) {
1226   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1227   int size;
1228   char *instr;
1229
1230   printIc (0, "genOr", ic, 1,1,1);
1231
1232   size=aopOp(result, TRUE, TRUE);
1233
1234   /* if left is a literal, then exchange them */
1235   if (IS_LITERAL(operandType(left))) {
1236     operand *tmp = right;
1237     right = left;
1238     left = tmp;
1239   }
1240     
1241   if (aopIsBit(result)) {
1242     if (IS_LITERAL(operandType(right))) {
1243       if (operandLitValue(right)) {
1244         emitcode ("setb", AOP_NAME(result)[0]);
1245         return;
1246       }
1247       aopOp(left, TRUE, TRUE);
1248       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1249       return;
1250     }
1251   }
1252   
1253   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1254   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1255
1256   if (size>1) {
1257     instr="or.w";
1258   } else {
1259     instr="or.b";
1260   }
1261   if (!aopEqual(result->aop, left->aop, 0)) {
1262     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1263   }
1264   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1265   if (size>2) {
1266     if (!aopEqual(result->aop, left->aop, 1)) {
1267       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1268     }
1269     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1270   }
1271   return;
1272 }
1273
1274 /*-----------------------------------------------------------------*/
1275 /* genXor - code for xclusive or                                   */
1276 /*-----------------------------------------------------------------*/
1277 static void genXor (iCode * ic, iCode * ifx) {
1278   printIc (0, "genXor", ic, 1,1,1);
1279 }
1280
1281 /*-----------------------------------------------------------------*/
1282 /* genInline - write the inline code out                           */
1283 /*-----------------------------------------------------------------*/
1284 static void genInline (iCode * ic) {
1285
1286   printIc (0, "genInline", ic, 0,0,0);
1287   
1288   emitcode ("", IC_INLINE(ic));
1289 }
1290
1291 /*-----------------------------------------------------------------*/
1292 /* genRRC - rotate right with carry                                */
1293 /*-----------------------------------------------------------------*/
1294 static void genRRC (iCode * ic) {
1295   printIc (0, "genRRC", ic, 1,1,0);
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* genRLC - generate code for rotate left with carry               */
1300 /*-----------------------------------------------------------------*/
1301 static void genRLC (iCode * ic) {
1302   printIc (0, "genRLC", ic, 1,1,0);
1303 }
1304
1305 /*-----------------------------------------------------------------*/
1306 /* genGetHbit - generates code get highest order bit               */
1307 /*-----------------------------------------------------------------*/
1308 static void genGetHbit (iCode * ic) {
1309   printIc (0, "genGetHbit", ic, 1,1,0);
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* genLeftShift - generates code for left shifting                 */
1314 /*-----------------------------------------------------------------*/
1315 static void genLeftShift (iCode * ic) {
1316   printIc (0, "genLeftShift", ic, 1,1,1);
1317 }
1318
1319 /*-----------------------------------------------------------------*/
1320 /* genRightShift - generate code for right shifting                */
1321 /*-----------------------------------------------------------------*/
1322 static void genRightShift (iCode * ic) {
1323   printIc (0, "genRightShift", ic, 1,1,1);
1324 }
1325
1326 /*-----------------------------------------------------------------*/
1327 /* genPointerGet - generate code for pointer get                   */
1328 /*-----------------------------------------------------------------*/
1329 static void genPointerGet (iCode * ic, iCode *pi) {
1330   char *instr, *scratchReg;
1331   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1332   bool codePointer=IS_CODEPTR(operandType(left));
1333   int size;
1334
1335   if (pi) {
1336     printIc (0, "genPointerGet pi", ic, 1,1,0);
1337   } else {
1338     printIc (0, "genPointerGet", ic, 1,1,0);
1339   }
1340
1341   if (!IS_PTR(operandType(left))) {
1342     bailOut ("genPointerGet: pointer required");
1343   }
1344
1345   aopOp(left,FALSE,FALSE);
1346   size=aopOp(result,TRUE,aopIsDir(left));
1347
1348   if (IS_GENPTR(operandType(left))) {
1349     symbol *tlbl1=newiTempLabel(NULL);
1350     symbol *tlbl2=newiTempLabel(NULL);
1351     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1352     emitcode ("beq", "%05d$", tlbl1->key+100);
1353     // far/near pointer
1354     if (pi) {
1355       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1356       pi->generated=1;
1357     } else {
1358       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1359     }
1360     if (size>2) {
1361       if (pi) {
1362         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1363       } else {
1364         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1365       }
1366     }
1367     emitcode ("br", "%05d$", tlbl2->key+100);
1368     emitcode ("", "%05d$:", tlbl1->key+100);
1369     // code pointer
1370     if (pi) {
1371       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1372       pi->generated=1;
1373     } else {
1374       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1375       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1376     }
1377     if (size>2) {
1378       if (pi) {
1379         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1380       } else {
1381         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1382       }
1383     }
1384     emitcode ("", "%05d$:", tlbl2->key+100);
1385     return;
1386   }
1387
1388   switch (AOP_TYPE(left)) 
1389     {
1390     case AOP_LIT:
1391       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1392       sprintf (AOP_NAME(left)[0], "r1");
1393       // fall through
1394     case AOP_REG:
1395       if (size>1) {
1396         if (codePointer) {
1397           instr=MOVCW;
1398         } else {
1399           instr=MOVW;
1400         }
1401         scratchReg=R1;
1402       } else {
1403         if (codePointer) {
1404           instr=MOVCB;
1405         } else {
1406           instr=MOVB;
1407         }
1408         scratchReg=R1L;
1409       }
1410       if (AOP_TYPE(result)==AOP_STK) {
1411         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1412         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1413       } else {
1414         if (pi) {
1415           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1416                     AOP_NAME(left)[0]);
1417           pi->generated=1;
1418         } else {
1419           if (codePointer) {
1420             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1421             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1422           } else {
1423             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1424                       AOP_NAME(left)[0]);
1425           }
1426         }
1427       }
1428       if (size > 2) {
1429         if (size==3) {
1430           if (codePointer) {
1431             instr=MOVCB;
1432           } else {
1433             instr=MOVB;
1434           }
1435           scratchReg=R1L;
1436         }
1437         if (AOP_TYPE(result)==AOP_STK) {
1438           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1439           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1440         } else {
1441           if (pi) {
1442             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1443                       AOP_NAME(left)[0]);
1444           } else {
1445             if (codePointer) {
1446               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1447             } else {
1448               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1449                         AOP_NAME(left)[0]);
1450             }
1451           }
1452         }
1453       }
1454       return;
1455     }
1456   bailOut ("genPointerGet");
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* genPointerSet - stores the value into a pointer location        */
1461 /*-----------------------------------------------------------------*/
1462 static void genPointerSet (iCode * ic, iCode *pi) {
1463   char *instr;
1464   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1465   int size;
1466
1467   printIc (0, "genPointerSet", ic, 1,0,1);
1468
1469   if (!IS_PTR(operandType(result))) {
1470     bailOut ("genPointerSet: pointer required");
1471   }
1472
1473   aopOp(result,FALSE,FALSE);
1474   size=aopOp(right,FALSE, FALSE);
1475
1476   if (IS_GENPTR(operandType(result))) {
1477     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1478               AOP_NAME(result)[0], AOP_NAME(result)[1],
1479               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1480     return;
1481   }
1482
1483   switch (AOP_TYPE(right)) 
1484     {
1485     case AOP_LIT:
1486     case AOP_REG:
1487       if (size>1) {
1488         instr=MOVW;
1489       } else {
1490         instr=MOVB;
1491       }
1492       if (pi) {
1493         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1494         pi->generated=1;
1495       } else {
1496         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1497       }
1498       if (size > 2) {
1499         if (size==3) {
1500           instr=MOVB;
1501         }
1502         if (pi) {
1503           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1504                     AOP_NAME(right)[1]);
1505         } else {
1506           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1507                     AOP_NAME(right)[1]);
1508         }
1509       }
1510       return;
1511     }
1512   bailOut ("genPointerSet");
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* genIfx - generate code for Ifx statement                        */
1517 /*-----------------------------------------------------------------*/
1518 static void genIfx (iCode * ic, iCode * popIc) {
1519   int size;
1520   char *instr;
1521   bool trueOrFalse;
1522   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1523   operand *cond=IC_COND(ic);
1524
1525   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1526             ic->lineno, printOp(cond),
1527             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1528             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1529
1530   size=aopOp(cond,TRUE,TRUE);
1531
1532   if (IC_TRUE(ic)) {
1533     trueOrFalse=TRUE;
1534     jlbl=IC_TRUE(ic);
1535   } else {
1536     trueOrFalse=FALSE;
1537     jlbl=IC_FALSE(ic);
1538   }
1539
1540   switch (AOP_TYPE(cond) )
1541     {
1542     case AOP_BIT:
1543       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1544                 AOP_NAME(cond)[0], tlbl->key+100);
1545       emitcode ("jmp", "%05d$", jlbl->key+100);
1546       emitcode ("", "%05d$:", tlbl->key+100);
1547       return;
1548     case AOP_REG:
1549     case AOP_DIR:
1550     case AOP_FAR:
1551     case AOP_STK:
1552       if (size>1) {
1553         instr="cmp.w";
1554       } else {
1555         instr="cmp.b";
1556       }
1557       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1558       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1559       if (size > 2) {
1560         if (size==3) {
1561           // generic pointer, forget the generic part
1562         } else {
1563           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1564           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1565         }
1566       }
1567       emitcode ("jmp", "%05d$", jlbl->key+100);
1568       emitcode ("", "%05d$:", tlbl->key+100);
1569       return;
1570     }
1571   bailOut ("genIfx");
1572 }
1573
1574 /*-----------------------------------------------------------------*/
1575 /* genAddrOf - generates code for address of                       */
1576 /*-----------------------------------------------------------------*/
1577 static void genAddrOf (iCode * ic) {
1578   int size;
1579   operand *left=IC_LEFT(ic);
1580
1581   printIc (0, "genAddrOf", ic, 1,1,0);
1582
1583   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1584
1585   if (isOperandOnStack(left)) {
1586     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1587               getStackOffset(OP_SYMBOL(left)->stack));
1588     if (size > 2) {
1589       // this must be a generic pointer
1590       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1591     }
1592     return;
1593   }
1594
1595   if (isOperandInDirSpace(left) ||
1596       isOperandInFarSpace(left) ||
1597       isOperandInCodeSpace(left)) {
1598     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1599               OP_SYMBOL(left)->rname);
1600     if (size > 2) {
1601       // this must be a generic pointer
1602       int space=0; // dir space
1603       if (isOperandInFarSpace(left)) {
1604         space=1;
1605       } else if (isOperandInCodeSpace(left)) {
1606         space=2;
1607       }
1608       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1609     }
1610     return;
1611   }
1612
1613   bailOut("genAddrOf");
1614 }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* genAssign - generate code for assignment                        */
1618 /*-----------------------------------------------------------------*/
1619 static void genAssign (iCode * ic) {
1620   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1621   int size;
1622   char *instr;
1623
1624   printIc (0, "genAssign", ic, 1,0,1);
1625   
1626   if (!IS_SYMOP(result)) {
1627     bailOut("genAssign: result is not a symbol");
1628   }
1629   
1630   aopOp(result, TRUE, TRUE);
1631   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1632   size=AOP_SIZE(result);
1633
1634   /* if result is a bit */
1635   if (AOP_TYPE(result) == AOP_BIT) {
1636     /* if right is literal, we know what the value is */
1637     if (AOP_TYPE(right) == AOP_LIT) {
1638       if (operandLitValue(right)) {
1639         emitcode ("setb", AOP_NAME(result)[0]);
1640       } else {
1641         emitcode ("clr", AOP_NAME(result)[0]);
1642       }
1643       return;
1644     }
1645     /* if right is also a bit */
1646     if (AOP_TYPE(right) == AOP_BIT) {
1647       emitcode ("mov", "c,%s", AOP_NAME(right));
1648       emitcode ("mov", "%s,c", AOP_NAME(result));
1649       return;
1650     }
1651     /* we need to or */
1652     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1653     return;
1654   }
1655
1656   // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1657   /* general case */
1658   if (size>1) {
1659     instr=MOVW;
1660   } else {
1661     instr=MOVB;
1662   }
1663   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1664
1665   if (size > 2) {
1666     if (size==3) {
1667       // generic pointer
1668       instr=MOVB;
1669     }
1670     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1671     return;
1672   }
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* genJumpTab - genrates code for jump table                       */
1677 /*-----------------------------------------------------------------*/
1678 static void genJumpTab (iCode * ic) {
1679   printIc (0, "genJumpTab", ic, 0,0,0);
1680 }
1681
1682 /*-----------------------------------------------------------------*/
1683 /* genCast - gen code for casting                                  */
1684 /*-----------------------------------------------------------------*/
1685 static void genCast (iCode * ic) {
1686   int size;
1687   operand *result=IC_RESULT(ic);
1688   operand *right=IC_RIGHT(ic);
1689   sym_link *ctype=operandType(IC_LEFT(ic));
1690   sym_link *rtype=operandType(IC_RIGHT(ic));
1691   sym_link *etype=getSpec(rtype);
1692   short ptrType, signedness;
1693
1694   printIc (0, "genCast", ic, 1,1,1);
1695
1696   aopOp(result, TRUE, TRUE);
1697   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1698   size=AOP_SIZE(result);
1699   
1700   /* if result is a bit */
1701   if (AOP_TYPE(result) == AOP_BIT) {
1702     /* if right is literal, we know what the value is */
1703     if (AOP_TYPE(right) == AOP_LIT) {
1704       if (operandLitValue(right)) {
1705         emitcode ("setb", AOP_NAME(result)[0]);
1706       } else {
1707         emitcode ("clr", AOP_NAME(result)[0]);
1708       }
1709       return;
1710     }
1711     /* if right is also a bit */
1712     if (AOP_TYPE(right) == AOP_BIT) {
1713       emitcode ("mov", "c,%s", AOP_NAME(right));
1714       emitcode ("mov", "%s,c", AOP_NAME(result));
1715       return;
1716     }
1717     /* we need to or */
1718     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1719     return;
1720   }
1721
1722   /* if right is a bit */
1723   if (AOP_TYPE(right)==AOP_BIT) {
1724     emitcode ("mov", "c,%s", AOP_NAME(right));
1725     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1726     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1727     if (size>2) {
1728       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1729     }
1730     return;
1731   }
1732
1733   /* if the result is of type pointer */
1734   if (IS_PTR (ctype)) {
1735
1736     if (AOP_SIZE(right)>1) {
1737       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1738     } else {
1739       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1740       emitcode ("sext", "r1h");
1741       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1742     }
1743     
1744     /* if pointer to generic pointer */
1745     if (IS_GENPTR (ctype)) {
1746             
1747       if (IS_GENPTR (rtype)) {
1748         bailOut("genCast: gptr -> gptr");
1749       }
1750
1751       if (IS_PTR (rtype)) {
1752         ptrType = DCL_TYPE (rtype);
1753       } else {
1754         /* we have to go by the storage class */
1755         if (!SPEC_OCLS(etype)) {
1756           ptrType=0; // hush the compiler
1757           bailOut("genCast: unknown storage class");
1758         } else {
1759           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1760         }
1761       }
1762       
1763       /* the generic part depends on the type */
1764       switch (ptrType)
1765         {
1766         case POINTER:
1767           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1768           break;
1769         case FPOINTER:
1770           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1771           break;
1772         case CPOINTER:
1773           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1774           break;
1775         default:
1776           bailOut("genCast: got unknown storage class");
1777         }
1778     }
1779     return;
1780   }
1781
1782   /* do we have to sign extend? */
1783   signedness = SPEC_USIGN(rtype);
1784
1785   /* now depending on the size */
1786   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1787     {
1788     case 0x44:
1789     case 0x33:
1790       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1791       // fall through
1792     case 0x24:
1793     case 0x22:
1794     case 0x11:
1795       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1796       return;
1797     case 0x42:
1798       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1799       if (signedness) {
1800         emitcode("sext", "%s", AOP_NAME(result)[1]);
1801       } else {
1802         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1803       }
1804       return;
1805     case 0x41:
1806     case 0x21:
1807       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1808       if (signedness) {
1809         emitcode("sext", "r1h");
1810       } else {
1811         emitcode("mov", "r1h,#0");
1812       }
1813       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1814       if (size==2)
1815         return;
1816       // fall through: case 0x41
1817       if (signedness) {
1818         emitcode("sext", "r1");
1819       } else {
1820         emitcode("mov", "r1,#0");
1821       }
1822       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1823       return;
1824     case 0x14:
1825     case 0x12:
1826       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1827       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1828       return;
1829     }
1830   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1831           AOP_SIZE(result), AOP_SIZE(right));
1832   bailOut("genCast: unknown size");
1833 }
1834
1835
1836 /*-----------------------------------------------------------------*/
1837 /* genDjnz - generate decrement & jump if not zero instrucion      */
1838 /*-----------------------------------------------------------------*/
1839 static bool genDjnz (iCode * ic, iCode * ifx) {
1840   symbol *lbl, *lbl1;
1841
1842   if (!ifx)
1843     return 0;
1844
1845   /* if the if condition has a false label
1846      then we cannot save */
1847   if (IC_FALSE (ifx))
1848     return 0;
1849
1850   /* if the minus is not of the form
1851      a = a - 1 */
1852   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1853       !IS_OP_LITERAL (IC_RIGHT (ic)))
1854     return 0;
1855
1856   if (operandLitValue (IC_RIGHT (ic)) != 1)
1857     return 0;
1858
1859   /* if the size of this greater than two then no
1860      saving */
1861   if (getSize (operandType (IC_RESULT (ic))) > 2)
1862     return 0;
1863
1864   printIc (0, "genDjnz", ic, 1,1,1);
1865
1866   /* otherwise we can save BIG */
1867   lbl = newiTempLabel (NULL);
1868   lbl1 = newiTempLabel (NULL);
1869
1870   aopOp (IC_RESULT (ic), FALSE, TRUE);
1871
1872   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1873     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1874     emitcode ("br", "%05d$", lbl1->key + 100);
1875     emitcode ("", "%05d$:", lbl->key + 100);
1876     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1877     emitcode ("", "%05d$:", lbl1->key + 100);
1878     return TRUE;
1879   }
1880
1881   bailOut("genDjnz: aop type");
1882   return FALSE;
1883 }
1884
1885 /*-----------------------------------------------------------------*/
1886 /* genReceive - generate code for a receive iCode                  */
1887 /*-----------------------------------------------------------------*/
1888 static void genReceive (iCode * ic) {
1889   printIc (0, "genReceive", ic, 1,0,0);
1890 }
1891
1892 /*-----------------------------------------------------------------*/
1893 /* genDummyRead - generate code for dummy read of volatiles        */
1894 /*-----------------------------------------------------------------*/
1895 static void
1896 genDummyRead (iCode * ic)
1897 {
1898   emitcode (";     genDummyRead","");
1899
1900   ic = ic;
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* gen51Code - generate code for 8051 based controllers            */
1905 /*-----------------------------------------------------------------*/
1906 void genXA51Code (iCode * lic) {
1907   iCode *ic;
1908   int cln = 0;
1909
1910   lineHead = lineCurr = NULL;
1911
1912   /* if debug information required */
1913   if (options.debug && currFunc)
1914     {
1915       debugFile->writeFunction(currFunc);
1916       _G.debugLine = 1;
1917       if (IS_STATIC (currFunc->etype))
1918         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1919       else
1920         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1921       _G.debugLine = 0;
1922     }
1923
1924   for (ic = lic; ic; ic = ic->next) {
1925     if (ic->lineno && cln != ic->lineno) {
1926       if (options.debug) {
1927         _G.debugLine = 1;
1928         emitcode ("", "C$%s$%d$%d$%d ==.",
1929                   FileBaseName (ic->filename), ic->lineno,
1930                   ic->level, ic->block);
1931         _G.debugLine = 0;
1932       }
1933       if (!options.noCcodeInAsm) {
1934         emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1935                   printCLine(ic->filename, ic->lineno));
1936       }
1937       cln = ic->lineno;
1938     }
1939     if (options.iCodeInAsm) {
1940       emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1941     }
1942
1943     /* if the result is marked as
1944        spilt and rematerializable or code for
1945        this has already been generated then
1946        do nothing */
1947     if (resultRemat (ic) || ic->generated)
1948       continue;
1949
1950     /* depending on the operation */
1951     switch (ic->op)
1952       {
1953       case '!':
1954         genNot (ic);
1955         break;
1956
1957       case '~':
1958         genCpl (ic);
1959         break;
1960
1961       case UNARYMINUS:
1962         genUminus (ic);
1963         break;
1964         
1965       case IPUSH:
1966         genIpush (ic);
1967         break;
1968         
1969       case IPOP:
1970         /* IPOP happens only when trying to restore a
1971            spilt live range, if there is an ifx statement
1972            following this pop then the if statement might
1973            be using some of the registers being popped which
1974            would destory the contents of the register so
1975            we need to check for this condition and handle it */
1976         if (ic->next &&
1977             ic->next->op == IFX &&
1978             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1979           genIfx (ic->next, ic);
1980         else
1981           genIpop (ic);
1982         break;
1983         
1984       case CALL:
1985         genCall (ic);
1986         break;
1987         
1988       case PCALL:
1989         genPcall (ic);
1990         break;
1991         
1992       case FUNCTION:
1993         genFunction (ic);
1994         break;
1995         
1996       case ENDFUNCTION:
1997         genEndFunction (ic);
1998         break;
1999         
2000       case RETURN:
2001         genRet (ic);
2002         break;
2003         
2004       case LABEL:
2005         genLabel (ic);
2006         break;
2007         
2008       case GOTO:
2009         genGoto (ic);
2010         break;
2011         
2012       case '+':
2013         genPlus (ic);
2014         break;
2015         
2016       case '-':
2017         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2018           genMinus (ic);
2019         break;
2020         
2021       case '*':
2022         genMult (ic);
2023         break;
2024         
2025       case '/':
2026         genDiv (ic);
2027         break;
2028         
2029       case '%':
2030         genMod (ic);
2031         break;
2032         
2033       case '>':
2034         genCmpGt (ic);
2035         break;
2036         
2037       case '<':
2038         genCmpLt (ic);
2039         break;
2040         
2041       case LE_OP:
2042       case GE_OP:
2043       case NE_OP:
2044
2045         /* note these two are xlated by algebraic equivalence
2046            during parsing SDCC.y */
2047         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2048                 "got '>=' or '<=' shouldn't have come here");
2049         break;
2050
2051       case EQ_OP:
2052         genCmpEq (ic);
2053         break;
2054         
2055       case AND_OP:
2056         genAndOp (ic);
2057         break;
2058         
2059       case OR_OP:
2060         genOrOp (ic);
2061         break;
2062         
2063       case '^':
2064         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2065         break;
2066         
2067       case '|':
2068         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2069         break;
2070         
2071       case BITWISEAND:
2072         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2073         break;
2074         
2075       case INLINEASM:
2076         genInline (ic);
2077         break;
2078         
2079       case RRC:
2080         genRRC (ic);
2081         break;
2082         
2083       case RLC:
2084         genRLC (ic);
2085         break;
2086
2087       case GETHBIT:
2088         genGetHbit (ic);
2089         break;
2090         
2091       case LEFT_OP:
2092         genLeftShift (ic);
2093         break;
2094         
2095       case RIGHT_OP:
2096         genRightShift (ic);
2097         break;
2098         
2099       case GET_VALUE_AT_ADDRESS:
2100         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2101         break;
2102         
2103       case '=':
2104         if (POINTER_SET (ic))
2105           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2106         else
2107           genAssign (ic);
2108         break;
2109         
2110       case IFX:
2111         genIfx (ic, NULL);
2112         break;
2113         
2114       case ADDRESS_OF:
2115         genAddrOf (ic);
2116         break;
2117         
2118       case JUMPTABLE:
2119         genJumpTab (ic);
2120         break;
2121         
2122       case CAST:
2123         genCast (ic);
2124         break;
2125         
2126       case RECEIVE:
2127         genReceive (ic);
2128         break;
2129
2130       case SEND:
2131         addSet (&_G.sendSet, ic);
2132         break;
2133
2134       case DUMMY_READ_VOLATILE:
2135         genDummyRead (ic);
2136         break;
2137
2138       default:
2139         ic = ic;
2140       }
2141   }
2142
2143
2144   /* now we are ready to call the
2145      peep hole optimizer */
2146   if (!options.nopeep)
2147     peepHole (&lineHead);
2148
2149   /* now do the actual printing */
2150   printLine (lineHead, codeOutFile);
2151   return;
2152 }