now it almost assembles using Paul's xa_asm.
[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       emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
955       if (AOP_SIZE(result) > 2) {
956         emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
957       }
958       return;
959     case AOP_REG:
960       emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
961       if (AOP_SIZE(result) > 2) {
962         // result is generic pointer
963         sym_link *optype=operandType(left);
964         sym_link *opetype=getSpec(optype);
965         if (IS_PTR(optype) && !IS_GENPTR(optype)) {
966           emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(result)[1], 
967                     PTR_TYPE(SPEC_OCLS(opetype)));
968         } else {
969           emitcode (instr, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
970         }
971       }
972       return;
973     case AOP_STK:
974       // if both on stack
975       if (AOP_TYPE(result)==AOP_STK) {
976         if (AOP_SIZE(result)==1) {
977           emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
978           emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
979         } else {
980           emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
981           emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
982         }
983       } else {
984         emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
985       }
986       if (AOP_SIZE(result) > 2) {
987         if (AOP_TYPE(result)==AOP_STK) {
988           if (AOP_SIZE(result)==3) {
989             emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
990             emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
991           } else {
992             emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
993             emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
994           }
995         } else {
996           emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
997         }
998       }
999       return;
1000     }
1001   bailOut ("genPointerGet: unknown pointer");
1002 }
1003
1004 /*-----------------------------------------------------------------*/
1005 /* genPointerSet - stores the value into a pointer location        */
1006 /*-----------------------------------------------------------------*/
1007 static void genPointerSet (iCode * ic, iCode *pi) {
1008   char *instr;
1009
1010   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1011
1012   printIc ("genPointerSet", ic, 1,0,1);
1013
1014   if (!IS_PTR(operandType(result))) {
1015     bailOut ("genPointerSet: pointer required");
1016   }
1017
1018   aopOp(right,FALSE);
1019   aopOp(result,TRUE);
1020
1021   if (IS_GENPTR(operandType(result))) {
1022     emitcode (";", "INLINE _gptrset ; [%s %s]=  %s %s", 
1023               AOP_NAME(result)[0], AOP_NAME(result)[1],
1024               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1025     return;
1026   }
1027
1028   switch (AOP_TYPE(result)) 
1029     {
1030     case AOP_REG:
1031     case AOP_DIR:
1032     case AOP_FAR:
1033     case AOP_STK:
1034       if (AOP_SIZE(result)==1) {
1035         instr=MOVB;
1036       } else {
1037         instr=MOVW;
1038       }
1039       emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1040       if (AOP_SIZE(result) > 2) {
1041         if (AOP_SIZE(result)==3) {
1042           instr=MOVB;
1043         } else {
1044           instr=MOVW;
1045         }
1046         emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1047       }
1048       return;
1049     }
1050   bailOut ("genPointerSet: unknown pointer");
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* genIfx - generate code for Ifx statement                        */
1055 /*-----------------------------------------------------------------*/
1056 static void genIfx (iCode * ic, iCode * popIc) {
1057   char *instr;
1058   bool trueOrFalse;
1059   symbol *jlbl, *tlbl;
1060   operand *cond=IC_COND(ic);
1061
1062   emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
1063             printOp(cond),
1064             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1065             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1066
1067   aopOp(cond,FALSE);
1068
1069   if (IC_TRUE(ic)) {
1070     trueOrFalse=TRUE;
1071     jlbl=IC_TRUE(ic);
1072   } else {
1073     trueOrFalse=FALSE;
1074     jlbl=IC_FALSE(ic);
1075   }
1076
1077   switch (AOP_TYPE(cond) )
1078     {
1079     case AOP_CRY:
1080       emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
1081                 AOP_NAME(cond)[0], jlbl->key+100);
1082       return;
1083     case AOP_REG:
1084     case AOP_DIR:
1085     case AOP_FAR:
1086     case AOP_STK:
1087       tlbl=newiTempLabel(NULL);
1088       if (AOP_SIZE(cond)==1) {
1089         instr="cmp.b";
1090       } else {
1091         instr="cmp.w";
1092       }
1093       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1094       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1095       if (AOP_SIZE(cond) > 2) {
1096         if (AOP_SIZE(cond)==3) {
1097           instr="cmp.b";
1098         } else {
1099           instr="cmp.w";
1100         }
1101         emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1102         emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1103       }
1104       emitcode ("jmp", "%05d$", jlbl->key+100);
1105       emitcode ("", "%05d$:", tlbl->key+100);
1106       return;
1107     }
1108   bailOut ("genIfx");
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genAddrOf - generates code for address of                       */
1113 /*-----------------------------------------------------------------*/
1114 static void genAddrOf (iCode * ic) {
1115   operand *left=IC_LEFT(ic);
1116
1117   printIc ("genAddrOf", ic, 1,1,0);
1118
1119   aopOp (IC_RESULT(ic),TRUE);
1120
1121   if (isOperandOnStack(left)) {
1122     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1123               getStackOffset(OP_SYMBOL(left)->stack));
1124     if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1125       // this must be a generic pointer
1126       emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
1127     }
1128     return;
1129   }
1130
1131   if (isOperandInDirSpace(left) ||
1132       isOperandInFarSpace(left) ||
1133       isOperandInCodeSpace(left)) {
1134     emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1135               OP_SYMBOL(left));
1136     if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1137       // this must be a generic pointer
1138       int space=0; // dir space
1139       if (isOperandInFarSpace(left)) {
1140         space=1;
1141       } else if (isOperandInCodeSpace(left)) {
1142         space=2;
1143       }
1144       emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1145     }
1146     return;
1147   }
1148
1149   bailOut("genAddrOf");
1150 }
1151
1152 /*-----------------------------------------------------------------*/
1153 /* genAssign - generate code for assignment                        */
1154 /*-----------------------------------------------------------------*/
1155 static void genAssign (iCode * ic) {
1156   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1157   int size;
1158   char *instr;
1159
1160   printIc ("genAssign", ic, 1,0,1);
1161   
1162   if (!IS_SYMOP(result)) {
1163     bailOut("genAssign: result is not a symbol");
1164   }
1165   
1166   aopOp(right, FALSE);
1167   aopOp(result, TRUE);
1168   size=AOP_SIZE(result);
1169
1170   if (result->aop->type==AOP_REG || 
1171       right->aop->type==AOP_REG ||
1172       right->aop->type==AOP_LIT ||
1173       right->aop->type==AOP_STK ||
1174       right->aop->type==AOP_IMMD) {
1175     // everything will do
1176   } else {
1177     // they have to match
1178     if (result->aop->type != right->aop->type) {
1179       fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1180                aopTypeName(result->aop), aopTypeName(right->aop));
1181       exit (1);
1182     }
1183   }
1184
1185   /* if result is a bit */
1186   if (AOP_TYPE(result) == AOP_CRY) {
1187     /* if right is literal, we know what the value is */
1188     if (AOP_TYPE(right) == AOP_LIT) {
1189       if (operandLitValue(right)) {
1190         emitcode ("setb", AOP_NAME(result)[0]);
1191       } else {
1192         emitcode ("clr", AOP_NAME(result)[0]);
1193       }
1194       return;
1195     }
1196     /* if right is also a bit */
1197     if (AOP_TYPE(right) == AOP_CRY) {
1198       emitcode ("mov", "c,%s", AOP_NAME(right));
1199       emitcode ("mov", "%s,c", AOP_NAME(result));
1200       return;
1201     }
1202     /* we need to or */
1203     emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1204     return;
1205   }
1206
1207   /* general case */
1208   if (size==1) {
1209     instr=MOVB;
1210   } else {
1211     instr=MOVW;
1212   }
1213   emitcode (instr, "%s,%s",
1214             result->aop->name[0], right->aop->name[0]);
1215   if (AOP_SIZE(result) > 2) {
1216     if (size==3) {
1217       instr=MOVB;
1218     } else {
1219       instr=MOVW;
1220     }
1221     emitcode (instr, "%s,%s",
1222               result->aop->name[1], right->aop->name[1]);
1223   }
1224   
1225 }
1226
1227 /*-----------------------------------------------------------------*/
1228 /* genJumpTab - genrates code for jump table                       */
1229 /*-----------------------------------------------------------------*/
1230 static void genJumpTab (iCode * ic) {
1231   printIc ("genJumpTab", ic, 0,0,0);
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* genCast - gen code for casting                                  */
1236 /*-----------------------------------------------------------------*/
1237 static void genCast (iCode * ic) {
1238   printIc ("genCast", ic, 1,1,1);
1239 }
1240
1241 /*-----------------------------------------------------------------*/
1242 /* genDjnz - generate decrement & jump if not zero instrucion      */
1243 /*-----------------------------------------------------------------*/
1244 static bool genDjnz (iCode * ic, iCode * ifx) {
1245   symbol *lbl, *lbl1;
1246
1247   if (!ifx)
1248     return 0;
1249
1250   /* if the if condition has a false label
1251      then we cannot save */
1252   if (IC_FALSE (ifx))
1253     return 0;
1254
1255   /* if the minus is not of the form
1256      a = a - 1 */
1257   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1258       !IS_OP_LITERAL (IC_RIGHT (ic)))
1259     return 0;
1260
1261   if (operandLitValue (IC_RIGHT (ic)) != 1)
1262     return 0;
1263
1264   /* if the size of this greater than two then no
1265      saving */
1266   if (getSize (operandType (IC_RESULT (ic))) > 2)
1267     return 0;
1268
1269   printIc ("genDjnz", ic, 1,1,1);
1270
1271   /* otherwise we can save BIG */
1272   lbl = newiTempLabel (NULL);
1273   lbl1 = newiTempLabel (NULL);
1274
1275   aopOp (IC_RESULT (ic), TRUE);
1276
1277   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1278     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1279     emitcode ("bra", "%05d$", lbl1->key + 100);
1280     emitcode ("", "%05d$:", lbl->key + 100);
1281     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1282     emitcode ("", "%05d$:", lbl1->key + 100);
1283     return TRUE;
1284   }
1285     bailOut("genDjnz: aop type");
1286     return FALSE;
1287 }
1288
1289 /*-----------------------------------------------------------------*/
1290 /* genReceive - generate code for a receive iCode                  */
1291 /*-----------------------------------------------------------------*/
1292 static void genReceive (iCode * ic) {
1293   printIc ("genReceive", ic, 1,0,0);
1294 }
1295
1296 /*-----------------------------------------------------------------*/
1297 /* gen51Code - generate code for 8051 based controllers            */
1298 /*-----------------------------------------------------------------*/
1299 void genXA51Code (iCode * lic) {
1300   iCode *ic;
1301   int cln = 0;
1302   
1303   fprintf (stderr, "genXA51Code\n");
1304   lineHead = lineCurr = NULL;
1305   
1306   /* print the allocation information */
1307   if (allocInfo)
1308     printAllocInfo (currFunc, codeOutFile);
1309
1310   /* if debug information required */
1311   if (options.debug && currFunc)
1312     {
1313       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1314       _G.debugLine = 1;
1315       if (IS_STATIC (currFunc->etype))
1316         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1317       else
1318         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1319       _G.debugLine = 0;
1320     }
1321   
1322   for (ic = lic; ic; ic = ic->next) {
1323     if (cln != ic->lineno) {
1324       if (options.debug) {
1325         _G.debugLine = 1;
1326         emitcode ("", "C$%s$%d$%d$%d ==.",
1327                   FileBaseName (ic->filename), ic->lineno,
1328                   ic->level, ic->block);
1329         _G.debugLine = 0;
1330       }
1331       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1332                 printCLine(ic->filename, ic->lineno));
1333       cln = ic->lineno;
1334     }
1335     /* if the result is marked as
1336        spilt and rematerializable or code for
1337        this has already been generated then
1338        do nothing */
1339     if (resultRemat (ic) || ic->generated)
1340       continue;
1341     
1342     /* depending on the operation */
1343     switch (ic->op)
1344       {
1345       case '!':
1346         genNot (ic);
1347         break;
1348         
1349       case '~':
1350         genCpl (ic);
1351         break;
1352         
1353       case UNARYMINUS:
1354         genUminus (ic);
1355         break;
1356         
1357       case IPUSH:
1358         genIpush (ic);
1359         break;
1360         
1361       case IPOP:
1362         /* IPOP happens only when trying to restore a
1363            spilt live range, if there is an ifx statement
1364            following this pop then the if statement might
1365            be using some of the registers being popped which
1366            would destory the contents of the register so
1367            we need to check for this condition and handle it */
1368         if (ic->next &&
1369             ic->next->op == IFX &&
1370             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1371           genIfx (ic->next, ic);
1372         else
1373           genIpop (ic);
1374         break;
1375         
1376       case CALL:
1377         genCall (ic);
1378         break;
1379         
1380       case PCALL:
1381         genPcall (ic);
1382         break;
1383         
1384       case FUNCTION:
1385         genFunction (ic);
1386         break;
1387         
1388       case ENDFUNCTION:
1389         genEndFunction (ic);
1390         break;
1391         
1392       case RETURN:
1393         genRet (ic);
1394         break;
1395         
1396       case LABEL:
1397         genLabel (ic);
1398         break;
1399         
1400       case GOTO:
1401         genGoto (ic);
1402         break;
1403         
1404       case '+':
1405         genPlus (ic);
1406         break;
1407         
1408       case '-':
1409         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1410           genMinus (ic);
1411         break;
1412         
1413       case '*':
1414         genMult (ic);
1415         break;
1416         
1417       case '/':
1418         genDiv (ic);
1419         break;
1420         
1421       case '%':
1422         genMod (ic);
1423         break;
1424         
1425       case '>':
1426         genCmpGt (ic);
1427         break;
1428         
1429       case '<':
1430         genCmpLt (ic);
1431         break;
1432         
1433       case LE_OP:
1434         genCmpLe (ic);
1435         break;
1436
1437       case GE_OP:
1438         genCmpGe (ic);
1439         break;
1440
1441       case NE_OP:
1442         genCmpNe (ic);
1443         break;
1444
1445       case EQ_OP:
1446         genCmpEq (ic);
1447         break;
1448         
1449       case AND_OP:
1450         genAndOp (ic);
1451         break;
1452         
1453       case OR_OP:
1454         genOrOp (ic);
1455         break;
1456         
1457       case '^':
1458         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1459         break;
1460         
1461       case '|':
1462         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1463         break;
1464         
1465       case BITWISEAND:
1466         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1467         break;
1468         
1469       case INLINEASM:
1470         genInline (ic);
1471         break;
1472         
1473       case RRC:
1474         genRRC (ic);
1475         break;
1476         
1477       case RLC:
1478         genRLC (ic);
1479         break;
1480         
1481       case GETHBIT:
1482         genGetHbit (ic);
1483         break;
1484         
1485       case LEFT_OP:
1486         genLeftShift (ic);
1487         break;
1488         
1489       case RIGHT_OP:
1490         genRightShift (ic);
1491         break;
1492         
1493       case GET_VALUE_AT_ADDRESS:
1494         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1495         break;
1496         
1497       case '=':
1498         if (POINTER_SET (ic))
1499           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1500         else
1501           genAssign (ic);
1502         break;
1503         
1504       case IFX:
1505         genIfx (ic, NULL);
1506         break;
1507         
1508       case ADDRESS_OF:
1509         genAddrOf (ic);
1510         break;
1511         
1512       case JUMPTABLE:
1513         genJumpTab (ic);
1514         break;
1515         
1516       case CAST:
1517         genCast (ic);
1518         break;
1519         
1520       case RECEIVE:
1521         genReceive (ic);
1522         break;
1523         
1524       case SEND:
1525         addSet (&_G.sendSet, ic);
1526         break;
1527         
1528       default:
1529         ic = ic;
1530       }
1531   }
1532   
1533   
1534   /* now we are ready to call the
1535      peep hole optimizer */
1536   if (!options.nopeep)
1537     peepHole (&lineHead);
1538   
1539   /* now do the actual printing */
1540   printLine (lineHead, codeOutFile);
1541   return;
1542 }