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