08e68fc36810e82c694416e73f0a019ed82c6079
[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
1901 /*-----------------------------------------------------------------*/
1902 /* gen51Code - generate code for 8051 based controllers            */
1903 /*-----------------------------------------------------------------*/
1904 void genXA51Code (iCode * lic) {
1905   iCode *ic;
1906   int cln = 0;
1907
1908   lineHead = lineCurr = NULL;
1909
1910   /* if debug information required */
1911   if (options.debug && currFunc)
1912     {
1913       debugFile->writeFunction(currFunc);
1914       _G.debugLine = 1;
1915       if (IS_STATIC (currFunc->etype))
1916         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1917       else
1918         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1919       _G.debugLine = 0;
1920     }
1921
1922   for (ic = lic; ic; ic = ic->next) {
1923     if (ic->lineno && cln != ic->lineno) {
1924       if (options.debug) {
1925         _G.debugLine = 1;
1926         emitcode ("", "C$%s$%d$%d$%d ==.",
1927                   FileBaseName (ic->filename), ic->lineno,
1928                   ic->level, ic->block);
1929         _G.debugLine = 0;
1930       }
1931       if (!options.noCcodeInAsm) {
1932         emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1933                   printCLine(ic->filename, ic->lineno));
1934       }
1935       cln = ic->lineno;
1936     }
1937     if (options.iCodeInAsm) {
1938       emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1939     }
1940
1941     /* if the result is marked as
1942        spilt and rematerializable or code for
1943        this has already been generated then
1944        do nothing */
1945     if (resultRemat (ic) || ic->generated)
1946       continue;
1947
1948     /* depending on the operation */
1949     switch (ic->op)
1950       {
1951       case '!':
1952         genNot (ic);
1953         break;
1954
1955       case '~':
1956         genCpl (ic);
1957         break;
1958
1959       case UNARYMINUS:
1960         genUminus (ic);
1961         break;
1962         
1963       case IPUSH:
1964         genIpush (ic);
1965         break;
1966         
1967       case IPOP:
1968         /* IPOP happens only when trying to restore a
1969            spilt live range, if there is an ifx statement
1970            following this pop then the if statement might
1971            be using some of the registers being popped which
1972            would destory the contents of the register so
1973            we need to check for this condition and handle it */
1974         if (ic->next &&
1975             ic->next->op == IFX &&
1976             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1977           genIfx (ic->next, ic);
1978         else
1979           genIpop (ic);
1980         break;
1981         
1982       case CALL:
1983         genCall (ic);
1984         break;
1985         
1986       case PCALL:
1987         genPcall (ic);
1988         break;
1989         
1990       case FUNCTION:
1991         genFunction (ic);
1992         break;
1993         
1994       case ENDFUNCTION:
1995         genEndFunction (ic);
1996         break;
1997         
1998       case RETURN:
1999         genRet (ic);
2000         break;
2001         
2002       case LABEL:
2003         genLabel (ic);
2004         break;
2005         
2006       case GOTO:
2007         genGoto (ic);
2008         break;
2009         
2010       case '+':
2011         genPlus (ic);
2012         break;
2013         
2014       case '-':
2015         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2016           genMinus (ic);
2017         break;
2018         
2019       case '*':
2020         genMult (ic);
2021         break;
2022         
2023       case '/':
2024         genDiv (ic);
2025         break;
2026         
2027       case '%':
2028         genMod (ic);
2029         break;
2030         
2031       case '>':
2032         genCmpGt (ic);
2033         break;
2034         
2035       case '<':
2036         genCmpLt (ic);
2037         break;
2038         
2039       case LE_OP:
2040       case GE_OP:
2041       case NE_OP:
2042
2043         /* note these two are xlated by algebraic equivalence
2044            during parsing SDCC.y */
2045         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2046                 "got '>=' or '<=' shouldn't have come here");
2047         break;
2048
2049       case EQ_OP:
2050         genCmpEq (ic);
2051         break;
2052         
2053       case AND_OP:
2054         genAndOp (ic);
2055         break;
2056         
2057       case OR_OP:
2058         genOrOp (ic);
2059         break;
2060         
2061       case '^':
2062         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2063         break;
2064         
2065       case '|':
2066         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2067         break;
2068         
2069       case BITWISEAND:
2070         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2071         break;
2072         
2073       case INLINEASM:
2074         genInline (ic);
2075         break;
2076         
2077       case RRC:
2078         genRRC (ic);
2079         break;
2080         
2081       case RLC:
2082         genRLC (ic);
2083         break;
2084
2085       case GETHBIT:
2086         genGetHbit (ic);
2087         break;
2088         
2089       case LEFT_OP:
2090         genLeftShift (ic);
2091         break;
2092         
2093       case RIGHT_OP:
2094         genRightShift (ic);
2095         break;
2096         
2097       case GET_VALUE_AT_ADDRESS:
2098         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2099         break;
2100         
2101       case '=':
2102         if (POINTER_SET (ic))
2103           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2104         else
2105           genAssign (ic);
2106         break;
2107         
2108       case IFX:
2109         genIfx (ic, NULL);
2110         break;
2111         
2112       case ADDRESS_OF:
2113         genAddrOf (ic);
2114         break;
2115         
2116       case JUMPTABLE:
2117         genJumpTab (ic);
2118         break;
2119         
2120       case CAST:
2121         genCast (ic);
2122         break;
2123         
2124       case RECEIVE:
2125         genReceive (ic);
2126         break;
2127
2128       case SEND:
2129         addSet (&_G.sendSet, ic);
2130         break;
2131
2132       case DUMMY_READ_VOLATILE:
2133         genDummyRead (ic);
2134         break;
2135
2136       default:
2137         ic = ic;
2138       }
2139   }
2140
2141
2142   /* now we are ready to call the
2143      peep hole optimizer */
2144   if (!options.nopeep)
2145     peepHole (&lineHead);
2146
2147   /* now do the actual printing */
2148   printLine (lineHead, codeOutFile);
2149   return;
2150 }