fixed bug #505806
[fw/sdcc] / src / xa51 / gen.c
1 /* The only ops for now are:
2    genAssign
3    genIfx
4    genAddrOf
5    genPointerSet
6    genPointerGet
7 */
8
9 /*-------------------------------------------------------------------------
10   SDCCgen51.c - source file for code generation for 8051
11
12   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
13          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
14   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
15
16   This program is free software; you can redistribute it and/or modify it
17   under the terms of the GNU General Public License as published by the
18   Free Software Foundation; either version 2, or (at your option) any
19   later version.
20
21   This program is distributed in the hope that it will be useful,
22   but WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24   GNU General Public License for more details.
25
26   You should have received a copy of the GNU General Public License
27   along with this program; if not, write to the Free Software
28   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
30   In other words, you are welcome to use, share and improve this program.
31   You are forbidden to forbid anyone else to use, share and improve
32   what you give them.   Help stamp out software-hoarding!
33
34   Notes:
35   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
36       Made everything static
37 -------------------------------------------------------------------------*/
38
39 //#define D(x)
40 #define D(x) x
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include "SDCCglobl.h"
47 #include "newalloc.h"
48
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
51 #else
52 #ifdef HAVE_MACHINE_ENDIAN_H
53 #include <machine/endian.h>
54 #else
55 #ifdef HAVE_ENDIAN_H
56 #include <endian.h>
57 #else
58 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
59 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
60 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
61 #endif
62 #endif
63 #endif
64 #endif
65
66 #include "common.h"
67 #include "SDCCpeeph.h"
68 #include "ralloc.h"
69 #include "gen.h"
70
71 #if defined(__BORLANDC__) || defined(_MSC_VER)
72 #define STRCASECMP stricmp
73 #else
74 #define STRCASECMP strcasecmp
75 #endif
76
77 extern int allocInfo;
78
79 /* this is the down and dirty file with all kinds of
80    kludgy & hacky stuff. This is what it is all about
81    CODE GENERATION for a specific MCU . some of the
82    routines may be reusable, will have to see */
83
84 static struct
85   {
86     short inLine;
87     short debugLine;
88     short nRegsSaved;
89     set *sendSet;
90   }
91 _G;
92
93 extern int xa51_ptrRegReq;
94 extern int xa51_nRegs;
95 extern FILE *codeOutFile;
96
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
99
100 #define LSB     0
101 #define MSB16   1
102 #define MSB24   2
103 #define MSB32   3
104
105 static char *MOVB="mov.b";
106 static char *MOVW="mov.w";
107 static char *MOVCB="movc.b";
108 static char *MOVCW="movc.w";
109
110 void bailOut (char *mesg) {
111   fprintf (stderr, "%s: bailing out\n", mesg);
112   exit (1);
113 }
114
115 /*-----------------------------------------------------------------*/
116 /* emitcode - writes the code into a file : for now it is simple    */
117 /*-----------------------------------------------------------------*/
118 static void emitcode (char *inst, char *fmt,...) {
119   va_list ap;
120   char lb[INITIAL_INLINEASM];
121   char *lbp = lb;
122
123   va_start (ap, fmt);
124
125   if (inst && *inst)
126     {
127       if (fmt && *fmt)
128         sprintf (lb, "%s\t", inst);
129       else
130         sprintf (lb, "%s", inst);
131       vsprintf (lb + (strlen (lb)), fmt, ap);
132     }
133   else
134     vsprintf (lb, fmt, ap);
135
136   while (isspace ((int)*lbp))
137     lbp++;
138
139   if (lbp && *lbp)
140     lineCurr = (lineCurr ?
141                 connectLine (lineCurr, newLineNode (lb)) :
142                 (lineHead = newLineNode (lb)));
143   lineCurr->isInline = _G.inLine;
144   lineCurr->isDebug = _G.debugLine;
145   va_end (ap);
146 }
147
148 char *getStackOffset(int stack) {
149   static char gsoBuf[1024];
150   // dit slaat natuurlijk nergens op
151   sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack,
152            FUNC_ISISR(currFunc->type) ? 
153              port->stack.isr_overhead : port->stack.call_overhead,
154            _G.nRegsSaved);
155   return gsoBuf;
156 }
157
158 /*-----------------------------------------------------------------*/
159 /* newAsmop - creates a new asmOp                                  */
160 /*-----------------------------------------------------------------*/
161 static asmop *
162 newAsmop (short type)
163 {
164   asmop *aop;
165
166   aop = Safe_calloc (1, sizeof (asmop));
167   aop->type = type;
168   return aop;
169 }
170
171 char *aopTypeName(asmop *aop) {
172   switch (aop->type)
173     {
174     case AOP_LIT: return "lit";
175     case AOP_REG: return "reg";
176     case AOP_DIR: return "dir";
177     case AOP_FAR: return "far";
178     case AOP_CODE: return "code";
179     case AOP_STK: return "stack";
180     case AOP_IMMD: return "imm";
181     case AOP_CRY: return "bit";
182     }
183   return "unknown";
184 }
185
186 /*-----------------------------------------------------------------*/
187 /* aopForSym - for a true symbol                                   */
188 /*-----------------------------------------------------------------*/
189 static asmop *aopForSym(symbol *sym, bool result) {
190   int size;
191   asmop *aop;
192
193   sym->aop = aop = newAsmop(0);
194   size=aop->size=getSize(sym->type);
195
196   // if the sym has registers
197   if (sym->nRegs && sym->regs[0]) {
198     aop->type=AOP_REG;
199     sprintf (aop->name[0], sym->regs[0]->name);
200     if (size>2) {
201       sprintf (aop->name[1], sym->regs[1]->name);
202     }
203     return aop;
204   }
205
206   // if it is on stack
207   if (sym->onStack) {
208     aop->type=AOP_STK;
209     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
210     if (size > 2) {
211       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
212     }
213     return aop;
214   }
215
216   // if it has a spillLoc
217   if (sym->usl.spillLoc) {
218     return aopForSym (sym->usl.spillLoc, result);
219   }
220
221   // if in bit space
222   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
223     aop->type=AOP_CRY;
224     sprintf (aop->name[0], sym->rname);
225     return aop;
226   }
227
228   // if in direct space
229   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
230     aop->type=AOP_DIR;
231     sprintf (aop->name[0], sym->rname);
232     if (size>2) {
233       sprintf (aop->name[0], "%s+2", sym->rname);
234     }
235     return aop;
236   }
237
238   // if in code space
239   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
240     if (result) {
241       bailOut("aopForSym: result can not be in code space");
242     }
243     aop->type=AOP_CODE;
244     emitcode ("mov", "r0,#%s", sym->rname);
245     sprintf (aop->name[0], "[r0]");
246     if (size>2) {
247       sprintf (aop->name[1], "[r0+1]");
248     }
249     return aop;
250   }
251
252   // if in far space
253   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
254     aop->type=AOP_FAR;
255     emitcode ("mov", "r0,#%s", sym->rname);
256     sprintf (aop->name[0], "[r0]");
257     if (size>2) {
258       sprintf (aop->name[1], "[r0+1]");
259     }
260     return aop;
261   }
262
263   bailOut("aopForSym");
264   return NULL;
265 }
266
267 /*-----------------------------------------------------------------*/
268 /* aopForVal - for a value                                         */
269 /*-----------------------------------------------------------------*/
270 static asmop *aopForVal(operand *op) {
271   asmop *aop;
272   long v=(long long)floatFromVal(OP_VALUE(op));
273
274   if (IS_OP_LITERAL(op)) {
275     op->aop = aop = newAsmop (AOP_LIT);
276     switch ((aop->size=getSize(operandType(op))))
277       {
278       case 1:
279         sprintf (aop->name[0], "#0x%02lx", v);
280         break;
281       case 2:
282         sprintf (aop->name[0], "#0x%04lx", v);
283         break;
284       case 4:
285         sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
286         sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
287         break;
288       default:
289         bailOut("aopForVal");
290       }
291     return aop;
292   }
293
294   // must be immediate
295   if (IS_SYMOP(op)) {
296     op->aop = aop = newAsmop (AOP_IMMD);
297     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
298       {
299       case 1:
300       case 2:
301         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
302         return aop;
303       case 3: // generic pointer
304         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
305         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
306         return aop;
307       }
308   }
309   bailOut ("aopForVal: unknown type");
310   return NULL;
311 }
312
313 static void aopOp(operand *op, bool result) {
314
315   if (IS_SYMOP(op)) {
316     op->aop=aopForSym (OP_SYMBOL(op), result);
317     return;
318   }
319   if (IS_VALOP(op)) {
320     if (result) {
321       bailOut("aopOp: result can not be a value");
322     }
323     aopForVal (op);
324     return;
325   }
326
327   bailOut("aopOp: unexpected operand");
328 }
329
330 char *opRegName(operand *op, int offset, char *opName) {
331
332   if (IS_SYMOP(op)) {
333     if (OP_SYMBOL(op)->onStack) {
334       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
335       return opName;
336     }
337     if (IS_TRUE_SYMOP(op))
338       return OP_SYMBOL(op)->rname;
339     else if (OP_SYMBOL(op)->regs[offset])
340       return OP_SYMBOL(op)->regs[offset]->name;
341     else
342       bailOut("opRegName: unknown regs");
343   }
344
345   if (IS_VALOP(op)) {
346     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
347     case V_SBIT:
348     case V_BIT:
349       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
350           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
351         bailOut("opRegName: invalid bit value");
352       }
353       // fall through
354     case V_CHAR:
355       sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
356       break;
357     case V_INT:
358       if (SPEC_LONG(OP_VALUE(op)->type)) {
359         sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
360       } else {
361         sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
362       }
363       break;
364     case V_FLOAT:
365       sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
366       break;
367     default: 
368       bailOut("opRegName: unexpected noun");
369     }
370     return opName;
371   }
372   bailOut("opRegName: unexpected operand type");
373   return NULL;
374 }
375
376 char * printOp (operand *op) {
377   static char line[132];
378   sym_link *optype=operandType(op);
379   bool isPtr = IS_PTR(optype);
380
381   if (IS_SYMOP(op)) {
382     symbol *sym=OP_SYMBOL(op);
383     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
384       sym=SYM_SPIL_LOC(sym);
385     }
386     if (isPtr) {
387       sprintf (line, "[");
388       if (DCL_TYPE(optype)==FPOINTER)
389         strcat (line, "far * ");
390       else if (DCL_TYPE(optype)==CPOINTER)
391         strcat (line, "code * ");
392       else if (DCL_TYPE(optype)==GPOINTER)
393         strcat (line, "gen * ");
394       else if (DCL_TYPE(optype)==POINTER)
395         strcat (line, "near * ");
396       else
397         strcat (line, "unknown * ");
398       strcat (line, "(");
399       strcat (line, nounName(sym->etype));
400       strcat (line, ")");
401       strcat (line, sym->name);
402       strcat (line, "]:");
403     } else {
404       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
405     }
406     if (sym->regs[0]) {
407       strcat (line, sym->regs[0]->name);
408       if (sym->regs[1]) {
409         strcat (line, ",");
410         strcat (line, sym->regs[1]->name);
411       }
412       return line;
413     }
414     if (sym->onStack) {
415       sprintf (line+strlen(line), "stack%+d", sym->stack);
416       return line;
417     }
418     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
419       strcat (line, "far");
420       return line;
421     }
422     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
423       strcat (line, "bit");
424       return line;
425     }
426     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
427       strcat (line, "dir");
428       return line;
429     }
430     strcat (line, "unknown");
431     return line;
432   } else if (IS_VALOP(op)) {
433     opRegName(op, 0, line);
434   } else if (IS_TYPOP(op)) {
435     sprintf (line, "[");
436     if (isPtr) {
437       if (DCL_TYPE(optype)==FPOINTER)
438         strcat (line, "far * ");
439       else if (DCL_TYPE(optype)==CPOINTER)
440         strcat (line, "code * ");
441       else if (DCL_TYPE(optype)==GPOINTER)
442         strcat (line, "gen * ");
443       else if (DCL_TYPE(optype)==POINTER)
444         strcat (line, "near * ");
445       else
446         strcat (line, "unknown * ");
447     }
448     // forget about static, volatile, ... for now
449     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
450     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
451     strcat (line, nounName(operandType(op)));
452     strcat (line, "]");
453   } else {
454     bailOut("printOp: unexpected operand type");
455   }
456   return line;
457 }
458
459 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
460   char line[132];
461
462   sprintf (line, "%s(%d)", op, ic->lineno);
463   if (result) {
464     strcat (line, " result=");
465     strcat (line, printOp (IC_RESULT(ic)));
466   }
467   if (left) {
468     strcat (line, " left=");
469     strcat (line, printOp (IC_LEFT(ic)));
470   }
471   if (right) {
472     strcat (line, " right=");
473     strcat (line, printOp (IC_RIGHT(ic)));
474   }
475   emitcode (";", line);
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* toBoolean - return carry for operand!=0                           */
480 /*-----------------------------------------------------------------*/
481 static char *toBoolean (operand * op) {
482   switch (AOP_SIZE(op)) 
483     {
484     case 1:
485     case 2:
486       emitcode ("cmp", "%s,#0", AOP_NAME(op));
487       emitcode ("mov", "c,z");
488       return "c";
489     }
490
491   bailOut("toBoolean: unknown size");
492   return NULL;
493 }
494
495 /*-----------------------------------------------------------------*/
496 /* regsInCommon - two operands have some registers in common       */
497 /*-----------------------------------------------------------------*/
498 static bool regsInCommon (operand * op1, operand * op2) {
499   symbol *sym1, *sym2;
500   int i;
501
502   /* if they have registers in common */
503   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
504     return FALSE;
505
506   sym1 = OP_SYMBOL (op1);
507   sym2 = OP_SYMBOL (op2);
508
509   if (sym1->nRegs == 0 || sym2->nRegs == 0)
510     return FALSE;
511
512   for (i = 0; i < sym1->nRegs; i++)
513     {
514       int j;
515       if (!sym1->regs[i])
516         continue;
517
518       for (j = 0; j < sym2->nRegs; j++)
519         {
520           if (!sym2->regs[j])
521             continue;
522
523           if (sym2->regs[j] == sym1->regs[i])
524             return TRUE;
525         }
526     }
527
528   return FALSE;
529 }
530
531 /*-----------------------------------------------------------------*/
532 /* resultRemat - result  is rematerializable                       */
533 /*-----------------------------------------------------------------*/
534 static int resultRemat (iCode * ic) {
535   if (SKIP_IC (ic) || ic->op == IFX)
536     return 0;
537   
538   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
539     {
540       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
541       if (sym->remat && !POINTER_SET (ic))
542         return 1;
543     }
544   
545   return 0;
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* genNot - generate code for ! operation                          */
550 /*-----------------------------------------------------------------*/
551 static void genNot (iCode * ic) {
552   printIc("genNot:", ic, 1,1,0);
553 }
554
555 /*-----------------------------------------------------------------*/
556 /* genCpl - generate code for complement                           */
557 /*-----------------------------------------------------------------*/
558 static void genCpl (iCode * ic) {
559   printIc("genCpl", ic, 1,1,0);
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* genUminus - unary minus code generation                         */
564 /*-----------------------------------------------------------------*/
565 static void genUminus (iCode * ic) {
566   printIc("genUminus", ic, 1,1,0);
567 }
568
569 /*-----------------------------------------------------------------*/
570 /* genIpush - genrate code for pushing this gets a little complex  */
571 /*-----------------------------------------------------------------*/
572 static void genIpush (iCode * ic) {
573   printIc ("genIpush", ic, 0,1,0);
574 }
575
576 /*-----------------------------------------------------------------*/
577 /* genIpop - recover the registers: can happen only for spilling   */
578 /*-----------------------------------------------------------------*/
579 static void genIpop (iCode * ic) {
580   printIc ("genIpop", ic, 0,1,0);
581 }
582
583 /*-----------------------------------------------------------------*/
584 /* genCall - generates a call statement                            */
585 /*-----------------------------------------------------------------*/
586 static void genCall (iCode * ic) {
587   emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
588             printOp (IC_RESULT(ic)));
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* genPcall - generates a call by pointer statement                */
593 /*-----------------------------------------------------------------*/
594 static void
595 genPcall (iCode * ic)
596 {
597   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
598 }
599
600 /*-----------------------------------------------------------------*/
601 /* genFunction - generated code for function entry                 */
602 /*-----------------------------------------------------------------*/
603 static void genFunction (iCode * ic) {
604   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
605   sym_link *type=sym->type;
606
607   emitcode (";", "-----------------------------------------");
608   emitcode (";", " function %s", sym->name);
609   emitcode (";", "-----------------------------------------");
610   
611   emitcode ("", "%s:", sym->rname);
612
613   if (IFFUNC_ISNAKED(type))
614   {
615       emitcode(";", "naked function: no prologue.");
616       return;
617   }
618
619   /* if critical function then turn interrupts off */
620   if (IFFUNC_ISCRITICAL (type))
621     emitcode ("clr", "ea");
622
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* genEndFunction - generates epilogue for functions               */
627 /*-----------------------------------------------------------------*/
628 static void
629 genEndFunction (iCode * ic)
630 {
631   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
632
633   if (IFFUNC_ISNAKED(sym->type))
634   {
635       emitcode(";", "naked function: no epilogue.");
636       return;
637   }
638
639   printIc ("genEndFunction", ic, 0,0,0);
640 }
641
642 /*-----------------------------------------------------------------*/
643 /* genRet - generate code for return statement                     */
644 /*-----------------------------------------------------------------*/
645 static void genRet (iCode * ic) {
646
647   printIc ("genRet", ic, 0,1,0);
648
649   aopOp(IC_LEFT(ic),FALSE);
650
651   switch (AOP_SIZE(IC_LEFT(ic)))
652     {
653     case 4:
654       emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
655       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
656       return;
657     case 3:
658       emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
659       // fall through
660     case 2:
661       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
662       return;
663     case 1:
664       emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
665       return;
666     }
667   bailOut("genRet");
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* genLabel - generates a label                                    */
672 /*-----------------------------------------------------------------*/
673 static void genLabel (iCode * ic) {
674   /* special case never generate */
675   if (IC_LABEL (ic) == entryLabel)
676     return;
677
678   emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
679   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
680 }
681
682 /*-----------------------------------------------------------------*/
683 /* genGoto - generates a jmp                                      */
684 /*-----------------------------------------------------------------*/
685 static void genGoto (iCode * ic) {
686   emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
687   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
688 }
689
690 /*-----------------------------------------------------------------*/
691 /* genPlus - generates code for addition                           */
692 /*-----------------------------------------------------------------*/
693 static void genPlus (iCode * ic) {
694   printIc ("genPlus", ic, 1,1,1);
695 }
696
697 /*-----------------------------------------------------------------*/
698 /* genMinus - generates code for subtraction                       */
699 /*-----------------------------------------------------------------*/
700 static void genMinus (iCode * ic) {
701   printIc ("genMinus", ic, 1,1,1);
702 }
703
704
705 /*-----------------------------------------------------------------*/
706 /* genMult - generates code for multiplication                     */
707 /*-----------------------------------------------------------------*/
708 static void genMult (iCode * ic) {
709   printIc ("genMult", ic, 1,1,1);
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* genDiv - generates code for division                            */
714 /*-----------------------------------------------------------------*/
715 static void genDiv (iCode * ic) {
716   printIc ("genDiv", ic, 1,1,1);
717 }
718
719 /*-----------------------------------------------------------------*/
720 /* genMod - generates code for division                            */
721 /*-----------------------------------------------------------------*/
722 static void genMod (iCode * ic) {
723   printIc ("genMod", ic, 1,1,1);
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* genCmpGt :- greater than comparison                             */
728 /*-----------------------------------------------------------------*/
729 static void genCmpGt (iCode * ic) {
730   printIc ("genCmpGt", ic, 1,1,1);
731 }
732 /*-----------------------------------------------------------------*/
733 /* genCmpGt :- greater than comparison                             */
734 /*-----------------------------------------------------------------*/
735 static void genCmpLe (iCode * ic) {
736   printIc ("genCmpGt", ic, 1,1,1);
737 }
738 /*-----------------------------------------------------------------*/
739 /* genCmpGt :- greater than comparison                             */
740 /*-----------------------------------------------------------------*/
741 static void genCmpGe (iCode * ic) {
742   printIc ("genCmpGt", ic, 1,1,1);
743 }
744 /*-----------------------------------------------------------------*/
745 /* genCmpGt :- greater than comparison                             */
746 /*-----------------------------------------------------------------*/
747 static void genCmpNe (iCode * ic) {
748   printIc ("genCmpGt", ic, 1,1,1);
749 }
750 /*-----------------------------------------------------------------*/
751 /* genCmpLt - less than comparisons                                */
752 /*-----------------------------------------------------------------*/
753 static void genCmpLt (iCode * ic) {
754   printIc ("genCmpLt", ic, 1,1,1);
755 }
756 /*-----------------------------------------------------------------*/
757 /* genCmpEq - generates code for equal to                          */
758 /*-----------------------------------------------------------------*/
759 static void genCmpEq (iCode * ic) {
760   printIc ("genCmpEq", ic, 1,1,1);
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* ifxForOp - returns the icode containing the ifx for operand     */
765 /*-----------------------------------------------------------------*/
766 static iCode *ifxForOp (operand * op, iCode * ic) {
767   /* if true symbol then needs to be assigned */
768   if (IS_TRUE_SYMOP (op))
769     return NULL;
770   
771   /* if this has register type condition and
772      the next instruction is ifx with the same operand
773      and live to of the operand is upto the ifx only then */
774   if (ic->next &&
775       ic->next->op == IFX &&
776       IC_COND (ic->next)->key == op->key &&
777       OP_SYMBOL (op)->liveTo <= ic->next->seq)
778     return ic->next;
779   
780   return NULL;
781 }
782
783 /*-----------------------------------------------------------------*/
784 /* hasInc - operand is incremented before any other use            */
785 /*-----------------------------------------------------------------*/
786 static iCode *hasInc (operand *op, iCode *ic, int osize) {
787   sym_link *type = operandType(op);
788   sym_link *retype = getSpec (type);
789   iCode *lic = ic->next;
790   int isize ;
791   
792   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
793   if (!IS_SYMOP(op)) return NULL;
794
795   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
796   if (IS_AGGREGATE(type->next)) return NULL;
797   if (osize != (isize = getSize(type->next))) return NULL;
798
799   while (lic) {
800     /* if operand of the form op = op + <sizeof *op> */
801     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
802         isOperandEqual(IC_RESULT(lic),op) && 
803         isOperandLiteral(IC_RIGHT(lic)) &&
804         operandLitValue(IC_RIGHT(lic)) == isize) {
805       return lic;
806     }
807     /* if the operand used or deffed */
808     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
809       return NULL;
810     }
811     /* if GOTO or IFX */
812     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
813     lic = lic->next;
814   }
815   return NULL;
816 }
817
818 /*-----------------------------------------------------------------*/
819 /* genAndOp - for && operation                                     */
820 /*-----------------------------------------------------------------*/
821 static void genAndOp (iCode * ic) {
822   printIc ("genAndOp(&&)", ic, 1,1,1);
823 }
824
825 /*-----------------------------------------------------------------*/
826 /* genOrOp - for || operation                                      */
827 /*-----------------------------------------------------------------*/
828 static void genOrOp (iCode * ic) {
829   printIc ("genOrOp(||)", ic, 1,1,1);
830 }
831
832 /*-----------------------------------------------------------------*/
833 /* genAnd  - code for and                                            */
834 /*-----------------------------------------------------------------*/
835 static void genAnd (iCode * ic, iCode * ifx) {
836   printIc ("genAnd", ic, 1,1,1);
837 }
838
839 /*-----------------------------------------------------------------*/
840 /* genOr  - code for or                                            */
841 /*-----------------------------------------------------------------*/
842 static void genOr (iCode * ic, iCode * ifx) {
843   printIc ("genOr", ic, 1,1,1);
844 }
845
846 /*-----------------------------------------------------------------*/
847 /* genXor - code for xclusive or                                   */
848 /*-----------------------------------------------------------------*/
849 static void genXor (iCode * ic, iCode * ifx) {
850   printIc ("genXor", ic, 1,1,1);
851 }
852
853 /*-----------------------------------------------------------------*/
854 /* genInline - write the inline code out                           */
855 /*-----------------------------------------------------------------*/
856 static void genInline (iCode * ic) {
857   printIc ("genInline", ic, 0,0,0);
858 }
859
860 /*-----------------------------------------------------------------*/
861 /* genRRC - rotate right with carry                                */
862 /*-----------------------------------------------------------------*/
863 static void genRRC (iCode * ic) {
864   printIc ("genRRC", ic, 1,1,0);
865 }
866
867 /*-----------------------------------------------------------------*/
868 /* genRLC - generate code for rotate left with carry               */
869 /*-----------------------------------------------------------------*/
870 static void genRLC (iCode * ic) {
871   printIc ("genRLC", ic, 1,1,0);
872 }
873
874 /*-----------------------------------------------------------------*/
875 /* genGetHbit - generates code get highest order bit               */
876 /*-----------------------------------------------------------------*/
877 static void genGetHbit (iCode * ic) {
878   printIc ("genGetHbit", ic, 1,1,0);
879 }
880
881 /*-----------------------------------------------------------------*/
882 /* genLeftShift - generates code for left shifting                 */
883 /*-----------------------------------------------------------------*/
884 static void genLeftShift (iCode * ic) {
885   printIc ("genLeftShift", ic, 1,1,1);
886 }
887
888 /*-----------------------------------------------------------------*/
889 /* genRightShift - generate code for right shifting                */
890 /*-----------------------------------------------------------------*/
891 static void genRightShift (iCode * ic) {
892   printIc ("genRightShift", ic, 1,1,1);
893 }
894
895 /*-----------------------------------------------------------------*/
896 /* genPointerGet - generate code for pointer get                   */
897 /*-----------------------------------------------------------------*/
898 static void genPointerGet (iCode * ic, iCode *pi) {
899   char *instr;
900
901   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
902
903   printIc ("genPointerGet", ic, 1,1,0);
904
905   if (!IS_PTR(operandType(left))) {
906     bailOut ("genPointerGet: pointer required");
907   }
908
909   aopOp(left,FALSE);
910   aopOp(result,TRUE);
911
912   if (IS_GENPTR(operandType(left))) {
913     emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]", 
914               AOP_NAME(result)[0], AOP_NAME(result)[1],
915               AOP_NAME(left)[0], AOP_NAME(left)[1]);
916     return;
917   }
918
919   switch (AOP_TYPE(left)) 
920     {
921     case AOP_CODE:
922       if (AOP_SIZE(result)==1) {
923         instr=MOVCB;
924       } else {
925         instr=MOVCW;
926       }
927       emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
928       if (AOP_SIZE(result) > 2) {
929         if (AOP_SIZE(result)==3) {
930           instr=MOVCB;
931         } else {
932           instr=MOVCW;
933         }
934         emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
935       }
936       return;
937     case AOP_FAR:
938       if (AOP_SIZE(result)==1) {
939         instr=MOVB;
940       } else {
941         instr=MOVW;
942       }
943       emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
944       if (AOP_SIZE(result) > 2) {
945         if (AOP_SIZE(result)==3) {
946           instr=MOVB;
947         } else {
948           instr=MOVW;
949         }
950         emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
951       }
952       return;
953     case AOP_DIR:
954       if (AOP_SIZE(result)==1) {
955         instr=MOVB;
956       } else {
957         instr=MOVW;
958       }
959       emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
960       if (AOP_SIZE(result) > 2) {
961         if (AOP_SIZE(result)==3) {
962           instr=MOVB;
963         } else {
964           instr=MOVW;
965         }
966         emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
967       }
968       return;
969     case AOP_REG:
970       if (AOP_SIZE(result)==1) {
971         instr=MOVB;
972       } else {
973         instr=MOVW;
974       }
975       emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
976       if (AOP_SIZE(result) > 2) {
977         // result is generic pointer
978         sym_link *optype=operandType(left);
979         sym_link *opetype=getSpec(optype);
980         if (IS_PTR(optype) && !IS_GENPTR(optype)) {
981           emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(result)[1], 
982                     PTR_TYPE(SPEC_OCLS(opetype)));
983         } else {
984           emitcode ("mov.b", "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
985         }
986       }
987       return;
988     case AOP_STK:
989       // if both on stack
990       if (AOP_TYPE(result)==AOP_STK) {
991         if (AOP_SIZE(result)==1) {
992           emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
993           emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
994         } else {
995           emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
996           emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
997         }
998       } else {
999         if (AOP_SIZE(result)==3) {
1000           emitcode ("mov.b", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1001         } else {
1002           emitcode ("mov.w", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1003         }
1004       }
1005       if (AOP_SIZE(result) > 2) {
1006         if (AOP_TYPE(result)==AOP_STK) {
1007           if (AOP_SIZE(result)==3) {
1008             emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
1009             emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
1010           } else {
1011             emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
1012             emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
1013           }
1014         } else {
1015           emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1016         }
1017       }
1018       return;
1019     }
1020   bailOut ("genPointerGet: unknown pointer");
1021 }
1022
1023 /*-----------------------------------------------------------------*/
1024 /* genPointerSet - stores the value into a pointer location        */
1025 /*-----------------------------------------------------------------*/
1026 static void genPointerSet (iCode * ic, iCode *pi) {
1027   char *instr;
1028
1029   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1030
1031   printIc ("genPointerSet", ic, 1,0,1);
1032
1033   if (!IS_PTR(operandType(result))) {
1034     bailOut ("genPointerSet: pointer required");
1035   }
1036
1037   aopOp(right,FALSE);
1038   aopOp(result,TRUE);
1039
1040   if (IS_GENPTR(operandType(result))) {
1041     emitcode (";", "INLINE _gptrset ; [%s %s]=  %s %s", 
1042               AOP_NAME(result)[0], AOP_NAME(result)[1],
1043               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1044     return;
1045   }
1046
1047   switch (AOP_TYPE(result)) 
1048     {
1049     case AOP_REG:
1050     case AOP_DIR:
1051     case AOP_FAR:
1052     case AOP_STK:
1053       if (AOP_SIZE(result)==1) {
1054         instr=MOVB;
1055       } else {
1056         instr=MOVW;
1057       }
1058       emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1059       if (AOP_SIZE(result) > 2) {
1060         if (AOP_SIZE(result)==3) {
1061           instr=MOVB;
1062         } else {
1063           instr=MOVW;
1064         }
1065         emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1066       }
1067       return;
1068     }
1069   bailOut ("genPointerSet: unknown pointer");
1070 }
1071
1072 /*-----------------------------------------------------------------*/
1073 /* genIfx - generate code for Ifx statement                        */
1074 /*-----------------------------------------------------------------*/
1075 static void genIfx (iCode * ic, iCode * popIc) {
1076   char *instr;
1077   bool trueOrFalse;
1078   symbol *jlbl, *tlbl;
1079   operand *cond=IC_COND(ic);
1080
1081   emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
1082             printOp(cond),
1083             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1084             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1085
1086   aopOp(cond,FALSE);
1087
1088   if (IC_TRUE(ic)) {
1089     trueOrFalse=TRUE;
1090     jlbl=IC_TRUE(ic);
1091   } else {
1092     trueOrFalse=FALSE;
1093     jlbl=IC_FALSE(ic);
1094   }
1095
1096   switch (AOP_TYPE(cond) )
1097     {
1098     case AOP_CRY:
1099       emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
1100                 AOP_NAME(cond)[0], jlbl->key+100);
1101       return;
1102     case AOP_REG:
1103     case AOP_DIR:
1104     case AOP_FAR:
1105     case AOP_STK:
1106       tlbl=newiTempLabel(NULL);
1107       if (AOP_SIZE(cond)==1) {
1108         instr="cmp.b";
1109       } else {
1110         instr="cmp.w";
1111       }
1112       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1113       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1114       if (AOP_SIZE(cond) > 2) {
1115         if (AOP_SIZE(cond)==3) {
1116           instr="cmp.b";
1117         } else {
1118           instr="cmp.w";
1119         }
1120         emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1121         emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1122       }
1123       emitcode ("jmp", "%05d$", jlbl->key+100);
1124       emitcode ("", "%05d$:", tlbl->key+100);
1125       return;
1126     }
1127   bailOut ("genIfx");
1128 }
1129
1130 /*-----------------------------------------------------------------*/
1131 /* genAddrOf - generates code for address of                       */
1132 /*-----------------------------------------------------------------*/
1133 static void genAddrOf (iCode * ic) {
1134   operand *left=IC_LEFT(ic);
1135
1136   printIc ("genAddrOf", ic, 1,1,0);
1137
1138   aopOp (IC_RESULT(ic),TRUE);
1139
1140   if (isOperandOnStack(left)) {
1141     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1142               getStackOffset(OP_SYMBOL(left)->stack));
1143     if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1144       // this must be a generic pointer
1145       emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
1146     }
1147     return;
1148   }
1149
1150   if (isOperandInDirSpace(left) ||
1151       isOperandInFarSpace(left) ||
1152       isOperandInCodeSpace(left)) {
1153     emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1154               OP_SYMBOL(left));
1155     if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1156       // this must be a generic pointer
1157       int space=0; // dir space
1158       if (isOperandInFarSpace(left)) {
1159         space=1;
1160       } else if (isOperandInCodeSpace(left)) {
1161         space=2;
1162       }
1163       emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1164     }
1165     return;
1166   }
1167
1168   bailOut("genAddrOf");
1169 }
1170
1171 /*-----------------------------------------------------------------*/
1172 /* genAssign - generate code for assignment                        */
1173 /*-----------------------------------------------------------------*/
1174 static void genAssign (iCode * ic) {
1175   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1176   int size;
1177   char *instr;
1178
1179   printIc ("genAssign", ic, 1,0,1);
1180   
1181   if (!IS_SYMOP(result)) {
1182     bailOut("genAssign: result is not a symbol");
1183   }
1184   
1185   aopOp(right, FALSE);
1186   aopOp(result, TRUE);
1187   size=AOP_SIZE(result);
1188
1189   if (result->aop->type==AOP_REG || 
1190       right->aop->type==AOP_REG ||
1191       right->aop->type==AOP_LIT ||
1192       right->aop->type==AOP_STK ||
1193       right->aop->type==AOP_IMMD) {
1194     // everything will do
1195   } else {
1196     // they have to match
1197     if (result->aop->type != right->aop->type) {
1198       fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1199                aopTypeName(result->aop), aopTypeName(right->aop));
1200       exit (1);
1201     }
1202   }
1203
1204   /* if result is a bit */
1205   if (AOP_TYPE(result) == AOP_CRY) {
1206     /* if right is literal, we know what the value is */
1207     if (AOP_TYPE(right) == AOP_LIT) {
1208       if (operandLitValue(right)) {
1209         emitcode ("setb", AOP_NAME(result)[0]);
1210       } else {
1211         emitcode ("clr", AOP_NAME(result)[0]);
1212       }
1213       return;
1214     }
1215     /* if right is also a bit */
1216     if (AOP_TYPE(right) == AOP_CRY) {
1217       emitcode ("mov", "c,%s", AOP_NAME(right));
1218       emitcode ("mov", "%s,c", AOP_NAME(result));
1219       return;
1220     }
1221     /* we need to or */
1222     emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1223     return;
1224   }
1225
1226   /* general case */
1227   if (size==1) {
1228     instr=MOVB;
1229   } else {
1230     instr=MOVW;
1231   }
1232   emitcode (instr, "%s,%s",
1233             result->aop->name[0], right->aop->name[0]);
1234   if (AOP_SIZE(result) > 2) {
1235     if (size==3) {
1236       instr=MOVB;
1237     } else {
1238       instr=MOVW;
1239     }
1240     emitcode (instr, "%s,%s",
1241               result->aop->name[1], right->aop->name[1]);
1242   }
1243   
1244 }
1245
1246 /*-----------------------------------------------------------------*/
1247 /* genJumpTab - genrates code for jump table                       */
1248 /*-----------------------------------------------------------------*/
1249 static void genJumpTab (iCode * ic) {
1250   printIc ("genJumpTab", ic, 0,0,0);
1251 }
1252
1253 /*-----------------------------------------------------------------*/
1254 /* genCast - gen code for casting                                  */
1255 /*-----------------------------------------------------------------*/
1256 static void genCast (iCode * ic) {
1257   printIc ("genCast", ic, 1,1,1);
1258 }
1259
1260 /*-----------------------------------------------------------------*/
1261 /* genDjnz - generate decrement & jump if not zero instrucion      */
1262 /*-----------------------------------------------------------------*/
1263 static bool genDjnz (iCode * ic, iCode * ifx) {
1264   symbol *lbl, *lbl1;
1265
1266   if (!ifx)
1267     return 0;
1268
1269   /* if the if condition has a false label
1270      then we cannot save */
1271   if (IC_FALSE (ifx))
1272     return 0;
1273
1274   /* if the minus is not of the form
1275      a = a - 1 */
1276   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1277       !IS_OP_LITERAL (IC_RIGHT (ic)))
1278     return 0;
1279
1280   if (operandLitValue (IC_RIGHT (ic)) != 1)
1281     return 0;
1282
1283   /* if the size of this greater than two then no
1284      saving */
1285   if (getSize (operandType (IC_RESULT (ic))) > 2)
1286     return 0;
1287
1288   printIc ("genDjnz", ic, 1,1,1);
1289
1290   /* otherwise we can save BIG */
1291   lbl = newiTempLabel (NULL);
1292   lbl1 = newiTempLabel (NULL);
1293
1294   aopOp (IC_RESULT (ic), TRUE);
1295
1296   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1297     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1298     emitcode ("bra", "%05d$", lbl1->key + 100);
1299     emitcode ("", "%05d$:", lbl->key + 100);
1300     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1301     emitcode ("", "%05d$:", lbl1->key + 100);
1302     return TRUE;
1303   }
1304     bailOut("genDjnz: aop type");
1305     return FALSE;
1306 }
1307
1308 /*-----------------------------------------------------------------*/
1309 /* genReceive - generate code for a receive iCode                  */
1310 /*-----------------------------------------------------------------*/
1311 static void genReceive (iCode * ic) {
1312   printIc ("genReceive", ic, 1,0,0);
1313 }
1314
1315 /*-----------------------------------------------------------------*/
1316 /* gen51Code - generate code for 8051 based controllers            */
1317 /*-----------------------------------------------------------------*/
1318 void genXA51Code (iCode * lic) {
1319   iCode *ic;
1320   int cln = 0;
1321   
1322   fprintf (stderr, "genXA51Code\n");
1323   lineHead = lineCurr = NULL;
1324   
1325   /* print the allocation information */
1326   if (allocInfo)
1327     printAllocInfo (currFunc, codeOutFile);
1328
1329   /* if debug information required */
1330   if (options.debug && currFunc)
1331     {
1332       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1333       _G.debugLine = 1;
1334       if (IS_STATIC (currFunc->etype))
1335         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1336       else
1337         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1338       _G.debugLine = 0;
1339     }
1340   
1341   for (ic = lic; ic; ic = ic->next) {
1342     if (cln != ic->lineno) {
1343       if (options.debug) {
1344         _G.debugLine = 1;
1345         emitcode ("", "C$%s$%d$%d$%d ==.",
1346                   FileBaseName (ic->filename), ic->lineno,
1347                   ic->level, ic->block);
1348         _G.debugLine = 0;
1349       }
1350       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1351                 printCLine(ic->filename, ic->lineno));
1352       cln = ic->lineno;
1353     }
1354     /* if the result is marked as
1355        spilt and rematerializable or code for
1356        this has already been generated then
1357        do nothing */
1358     if (resultRemat (ic) || ic->generated)
1359       continue;
1360     
1361     /* depending on the operation */
1362     switch (ic->op)
1363       {
1364       case '!':
1365         genNot (ic);
1366         break;
1367         
1368       case '~':
1369         genCpl (ic);
1370         break;
1371         
1372       case UNARYMINUS:
1373         genUminus (ic);
1374         break;
1375         
1376       case IPUSH:
1377         genIpush (ic);
1378         break;
1379         
1380       case IPOP:
1381         /* IPOP happens only when trying to restore a
1382            spilt live range, if there is an ifx statement
1383            following this pop then the if statement might
1384            be using some of the registers being popped which
1385            would destory the contents of the register so
1386            we need to check for this condition and handle it */
1387         if (ic->next &&
1388             ic->next->op == IFX &&
1389             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1390           genIfx (ic->next, ic);
1391         else
1392           genIpop (ic);
1393         break;
1394         
1395       case CALL:
1396         genCall (ic);
1397         break;
1398         
1399       case PCALL:
1400         genPcall (ic);
1401         break;
1402         
1403       case FUNCTION:
1404         genFunction (ic);
1405         break;
1406         
1407       case ENDFUNCTION:
1408         genEndFunction (ic);
1409         break;
1410         
1411       case RETURN:
1412         genRet (ic);
1413         break;
1414         
1415       case LABEL:
1416         genLabel (ic);
1417         break;
1418         
1419       case GOTO:
1420         genGoto (ic);
1421         break;
1422         
1423       case '+':
1424         genPlus (ic);
1425         break;
1426         
1427       case '-':
1428         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1429           genMinus (ic);
1430         break;
1431         
1432       case '*':
1433         genMult (ic);
1434         break;
1435         
1436       case '/':
1437         genDiv (ic);
1438         break;
1439         
1440       case '%':
1441         genMod (ic);
1442         break;
1443         
1444       case '>':
1445         genCmpGt (ic);
1446         break;
1447         
1448       case '<':
1449         genCmpLt (ic);
1450         break;
1451         
1452       case LE_OP:
1453         genCmpLe (ic);
1454         break;
1455
1456       case GE_OP:
1457         genCmpGe (ic);
1458         break;
1459
1460       case NE_OP:
1461         genCmpNe (ic);
1462         break;
1463
1464       case EQ_OP:
1465         genCmpEq (ic);
1466         break;
1467         
1468       case AND_OP:
1469         genAndOp (ic);
1470         break;
1471         
1472       case OR_OP:
1473         genOrOp (ic);
1474         break;
1475         
1476       case '^':
1477         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1478         break;
1479         
1480       case '|':
1481         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1482         break;
1483         
1484       case BITWISEAND:
1485         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1486         break;
1487         
1488       case INLINEASM:
1489         genInline (ic);
1490         break;
1491         
1492       case RRC:
1493         genRRC (ic);
1494         break;
1495         
1496       case RLC:
1497         genRLC (ic);
1498         break;
1499         
1500       case GETHBIT:
1501         genGetHbit (ic);
1502         break;
1503         
1504       case LEFT_OP:
1505         genLeftShift (ic);
1506         break;
1507         
1508       case RIGHT_OP:
1509         genRightShift (ic);
1510         break;
1511         
1512       case GET_VALUE_AT_ADDRESS:
1513         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1514         break;
1515         
1516       case '=':
1517         if (POINTER_SET (ic))
1518           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1519         else
1520           genAssign (ic);
1521         break;
1522         
1523       case IFX:
1524         genIfx (ic, NULL);
1525         break;
1526         
1527       case ADDRESS_OF:
1528         genAddrOf (ic);
1529         break;
1530         
1531       case JUMPTABLE:
1532         genJumpTab (ic);
1533         break;
1534         
1535       case CAST:
1536         genCast (ic);
1537         break;
1538         
1539       case RECEIVE:
1540         genReceive (ic);
1541         break;
1542         
1543       case SEND:
1544         addSet (&_G.sendSet, ic);
1545         break;
1546         
1547       default:
1548         ic = ic;
1549       }
1550   }
1551   
1552   
1553   /* now we are ready to call the
1554      peep hole optimizer */
1555   if (!options.nopeep)
1556     peepHole (&lineHead);
1557   
1558   /* now do the actual printing */
1559   printLine (lineHead, codeOutFile);
1560   return;
1561 }