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