xa51 backup
[fw/sdcc] / src / xa51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26 -------------------------------------------------------------------------*/
27
28 //#define D(x)
29 #define D(x) x
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
43 #else
44 #ifdef HAVE_ENDIAN_H
45 #include <endian.h>
46 #else
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
50 #endif
51 #endif
52 #endif
53 #endif
54
55 #include "common.h"
56 #include "SDCCpeeph.h"
57 #include "ralloc.h"
58 #include "gen.h"
59
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
62 #else
63 #define STRCASECMP strcasecmp
64 #endif
65
66 extern int allocInfo;
67
68 /* this is the down and dirty file with all kinds of
69    kludgy & hacky stuff. This is what it is all about
70    CODE GENERATION for a specific MCU . some of the
71    routines may be reusable, will have to see */
72
73 static struct
74   {
75     short inLine;
76     short debugLine;
77     short stackExtend;
78     short nRegsSaved;
79     short parmsPushed;
80     set *sendSet;
81   }
82 _G;
83
84 extern int xa51_ptrRegReq;
85 extern int xa51_nRegs;
86 extern FILE *codeOutFile;
87
88 static lineNode *lineHead = NULL;
89 static lineNode *lineCurr = NULL;
90
91 #define LSB     0
92 #define MSB16   1
93 #define MSB24   2
94 #define MSB32   3
95
96 static char *MOV="mov";
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 static char *MOVC="movc";
100 static char *MOVCB="movc.b";
101 static char *MOVCW="movc.w";
102
103 static char *R1L="r1l";
104 static char *R1="r1";
105
106 void bailOut (char *mesg) {
107   fprintf (stderr, "%s: bailing out\n", mesg);
108   exit (1);
109 }
110
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple    */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst, char *fmt,...) {
115   va_list ap;
116   char lb[INITIAL_INLINEASM];
117   char *lbp = lb;
118
119   va_start (ap, fmt);
120
121   if (inst && *inst)
122     {
123       if (fmt && *fmt)
124         sprintf (lb, "%s\t", inst);
125       else
126         sprintf (lb, "%s", inst);
127       vsprintf (lb + (strlen (lb)), fmt, ap);
128     }
129   else
130     vsprintf (lb, fmt, ap);
131
132   while (isspace ((int)*lbp))
133     lbp++;
134
135   if (lbp && *lbp)
136     lineCurr = (lineCurr ?
137                 connectLine (lineCurr, newLineNode (lb)) :
138                 (lineHead = newLineNode (lb)));
139   lineCurr->isInline = _G.inLine;
140   lineCurr->isDebug = _G.debugLine;
141   va_end (ap);
142 }
143
144 char *getStackOffset(int stack) {
145   static char gsoBuf[1024];
146   sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
147            currFunc->stack, _G.nRegsSaved);
148   return gsoBuf;
149 }
150
151 /*-----------------------------------------------------------------*/
152 /* newAsmop - creates a new asmOp                                  */
153 /*-----------------------------------------------------------------*/
154 static asmop *
155 newAsmop (short type)
156 {
157   asmop *aop;
158
159   aop = Safe_calloc (1, sizeof (asmop));
160   aop->type = type;
161   return aop;
162 }
163
164 char *aopTypeName(asmop *aop) {
165   switch (aop->type)
166     {
167     case AOP_LIT: return "lit";
168     case AOP_REG: return "reg";
169     case AOP_DIR: return "dir";
170     case AOP_FAR: return "far";
171     case AOP_CODE: return "code";
172     case AOP_GPTR: return "gptr";
173     case AOP_STK: return "stack";
174     case AOP_IMMD: return "imm";
175     case AOP_BIT: return "bit";
176     }
177   return "unknown";
178 }
179
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol                                   */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym, 
184                         bool canUsePointer, bool canUseOffset) {
185   int size;
186   asmop *aop;
187
188   sym->aop = aop = newAsmop(0);
189   size=aop->size=getSize(sym->type);
190
191   // if the sym has registers
192   if (sym->nRegs && sym->regs[0]) {
193     aop->type=AOP_REG;
194     sprintf (aop->name[0], sym->regs[0]->name);
195     if (size > 2) {
196       sprintf (aop->name[1], sym->regs[1]->name);
197     }
198     return aop;
199   }
200
201   // if it is on stack
202   if (sym->onStack) {
203     if (!canUsePointer || !canUseOffset) {
204       aop->type=AOP_REG;
205       switch (size) 
206         {
207         case 1:
208           emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack));
209           sprintf (aop->name[0], "r0l");
210           return aop;
211         case 2:
212           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
213           sprintf (aop->name[0], "r0");
214           return aop;
215         case 3:
216           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
217           sprintf (aop->name[0], "r0");
218           emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
219           sprintf (aop->name[1], "r1l");
220           return aop;
221         case 4:
222           emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
223           sprintf (aop->name[0], "r0");
224           emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2));
225           sprintf (aop->name[1], "r1");
226           return aop;
227         }
228     }
229     aop->type=AOP_STK;
230     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
231     if (size > 2) {
232       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
233     }
234     return aop;
235   }
236
237   // if it has a spillLoc
238   if (sym->usl.spillLoc) {
239     return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
240   }
241
242   // if in bit space
243   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
244     aop->type=AOP_BIT;
245     sprintf (aop->name[0], sym->rname);
246     return aop;
247   }
248
249   // if in direct space
250   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
251     aop->type=AOP_DIR;
252     sprintf (aop->name[0], sym->rname);
253     if (size>2) {
254       sprintf (aop->name[1], "%s+2", sym->rname);
255     }
256     return aop;
257   }
258
259   // if in code space
260   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261     if (!canUsePointer) {
262       aop->type=AOP_REG;
263       switch (size) 
264         {
265         case 1:
266           emitcode (MOV, "r0,#%s", sym->rname);
267           emitcode (MOVC, "r0l,[r0+]");
268           sprintf (aop->name[0], "r0l");
269           return aop;
270         case 2:
271           emitcode (MOV, "r0,#%s", sym->rname);
272           emitcode (MOVC, "r0,[r0+]");
273           sprintf (aop->name[0], "r0");
274           return aop;
275         case 3:
276           emitcode (MOV, "r0,#%s", sym->rname);
277           emitcode (MOVC, "r0,[r0+]");
278           sprintf (aop->name[1], "r0");
279           emitcode (MOV, "r1l,[r0+]");
280           sprintf (aop->name[0], "r1l");
281           return aop;
282         case 4:
283           emitcode (MOV, "r0,#%s", sym->rname);
284           emitcode (MOVC, "r1,[r0+]");
285           emitcode (MOVC, "r0,[r0+]");
286           emitcode ("xch", "r0,r1");
287           sprintf (aop->name[0], "r0");
288           sprintf (aop->name[1], "r1");
289           return aop;
290         }
291       
292     } else {
293       aop->type=AOP_CODE;
294       emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
295       sprintf (aop->name[0], "[r0]");
296       if (size>2) {
297         sprintf (aop->name[1], "[r0+2]");
298       }
299     }
300     return aop;
301   }
302
303   // if in far space
304   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
305     if (!canUsePointer) {
306       aop->type=AOP_REG;
307       switch (size) 
308         {
309         case 1:
310           emitcode (MOV, "r0,#%s", sym->rname);
311           emitcode (MOV, "r0l,[r0]");
312           sprintf (aop->name[0], "r0l");
313           return aop;
314         case 2:
315           emitcode (MOV, "r0,#%s", sym->rname);
316           emitcode (MOV, "r0,[r0]");
317           sprintf (aop->name[0], "r0");
318           return aop;
319         case 3:
320           emitcode (MOV, "r0,#%s", sym->rname);
321           emitcode (MOV, "r1l,[r0+2]");
322           sprintf (aop->name[1], "r1l");
323           emitcode (MOV, "r0,[r0]");
324           sprintf (aop->name[0], "r0");
325           return aop;
326         case 4:
327           emitcode (MOV, "r0,#%s", sym->rname);
328           emitcode (MOV, "r1,[r0+2]");
329           sprintf (aop->name[1], "r1");
330           emitcode (MOV, "r0,[r0]");
331           sprintf (aop->name[0], "r0");
332           return aop;
333         }
334     } else {
335       aop->type=AOP_FAR;
336       emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
337       sprintf (aop->name[0], "[r0]");
338       if (size>2) {
339         sprintf (aop->name[1], "[r0+2]");
340       }
341       return aop;
342     }
343   }
344   
345   bailOut("aopForSym");
346   return NULL;
347 }
348
349 /*-----------------------------------------------------------------*/
350 /* aopForVal - for a value                                         */
351 /*-----------------------------------------------------------------*/
352 static asmop *aopForVal(operand *op) {
353   asmop *aop;
354
355   if (IS_OP_LITERAL(op)) {
356     op->aop = aop = newAsmop (AOP_LIT);
357     switch ((aop->size=getSize(operandType(op))))
358       {
359       case 1:
360         sprintf (aop->name[0], "#0x%02x", 
361                  SPEC_CVAL(operandType(op)).v_int & 0xff);
362         sprintf (aop->name[1], "#0");
363         break;
364       case 2:
365         sprintf (aop->name[0], "#0x%04x", 
366                  SPEC_CVAL(operandType(op)).v_int & 0xffff);
367         sprintf (aop->name[1], "#0");
368         break;
369       case 3:
370         // must be a generic pointer, can only be zero
371         // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
372         sprintf (aop->name[0], "#0x%04x", 
373                  SPEC_CVAL(operandType(op)).v_uint & 0xffff);
374         sprintf (aop->name[1], "#0");
375         break;
376       case 4:
377         sprintf (aop->name[0], "#0x%04lx",
378                  SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
379         sprintf (aop->name[1], "#0x%04lx", 
380                  SPEC_CVAL(operandType(op)).v_ulong >> 16);
381         break;
382       default:
383         bailOut("aopForVal");
384       }
385     return aop;
386   }
387
388   // must be immediate
389   if (IS_SYMOP(op)) {
390     op->aop = aop = newAsmop (AOP_IMMD);
391     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
392       {
393       case 1:
394       case 2:
395         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
396         return aop;
397       case 3: // generic pointer
398         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
399         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
400         return aop;
401       }
402   }
403
404   bailOut ("aopForVal: unknown type");
405   return NULL;
406 }
407
408 static int aopOp(operand *op, 
409                   bool canUsePointer, bool canUseOffset) {
410
411   if (IS_SYMOP(op)) {
412     op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
413     return AOP_SIZE(op);
414   }
415   if (IS_VALOP(op)) {
416     op->aop=aopForVal (op);
417     return AOP_SIZE(op);
418   }
419
420   bailOut("aopOp: unexpected operand");
421   return 0;
422 }
423
424 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
425   if (strcmp(aop1->name[offset], aop2->name[offset])) {
426     return FALSE;
427   }
428   return TRUE;
429 }
430
431 bool aopIsDir(operand *op) {
432   return AOP_TYPE(op)==AOP_DIR;
433 }
434
435 bool aopIsBit(operand *op) {
436   return AOP_TYPE(op)==AOP_BIT;
437 }
438
439 bool aopIsPtr(operand *op) {
440   if (AOP_TYPE(op)==AOP_STK ||
441       AOP_TYPE(op)==AOP_CODE ||
442       AOP_TYPE(op)==AOP_FAR) {
443     return TRUE;
444   } else {
445     return FALSE;
446   }
447 }
448       
449 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
450
451   if (IS_SYMOP(op)) {
452     if (OP_SYMBOL(op)->onStack) {
453       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
454       return opName;
455     }
456     if (IS_TRUE_SYMOP(op))
457       return OP_SYMBOL(op)->rname;
458     else if (OP_SYMBOL(op)->regs[offset])
459       return OP_SYMBOL(op)->regs[offset]->name;
460     else
461       bailOut("opRegName: unknown regs");
462   }
463
464   if (IS_VALOP(op)) {
465     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
466     case V_SBIT:
467     case V_BIT:
468       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
469           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
470         bailOut("opRegName: invalid bit value");
471       }
472       // fall through
473     case V_CHAR:
474       sprintf (opName, "#%s0x%02x", decorate?"(char)":"", 
475                SPEC_CVAL(OP_VALUE(op)->type).v_int);
476       break;
477     case V_INT:
478       if (SPEC_LONG(OP_VALUE(op)->type)) {
479         sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
480                  SPEC_CVAL(OP_VALUE(op)->type).v_long);
481       } else {
482         sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
483                  SPEC_CVAL(OP_VALUE(op)->type).v_int);
484       }
485       break;
486     case V_FLOAT:
487       sprintf (opName, "#%s%f", decorate?"(float)":"",
488                SPEC_CVAL(OP_VALUE(op)->type).v_float);
489       break;
490     default: 
491       bailOut("opRegName: unexpected noun");
492     }
493     return opName;
494   }
495   bailOut("opRegName: unexpected operand type");
496   return NULL;
497 }
498
499 char * printOp (operand *op) {
500   static char line[132];
501   sym_link *optype=operandType(op);
502   bool isPtr = IS_PTR(optype);
503
504   if (IS_SYMOP(op)) {
505     symbol *sym=OP_SYMBOL(op);
506     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
507       sym=SYM_SPIL_LOC(sym);
508     }
509     if (isPtr) {
510       sprintf (line, "[");
511       if (DCL_TYPE(optype)==FPOINTER)
512         strcat (line, "far * ");
513       else if (DCL_TYPE(optype)==CPOINTER)
514         strcat (line, "code * ");
515       else if (DCL_TYPE(optype)==GPOINTER)
516         strcat (line, "gen * ");
517       else if (DCL_TYPE(optype)==POINTER)
518         strcat (line, "near * ");
519       else
520         strcat (line, "unknown * ");
521       strcat (line, "(");
522       strcat (line, nounName(sym->etype));
523       strcat (line, ")");
524       strcat (line, sym->name);
525       strcat (line, "]:");
526     } else {
527       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
528     }
529     if (sym->regs[0]) {
530       strcat (line, sym->regs[0]->name);
531       if (sym->regs[1]) {
532         strcat (line, ",");
533         strcat (line, sym->regs[1]->name);
534       }
535       return line;
536     }
537     if (sym->onStack) {
538       sprintf (line+strlen(line), "stack%+d", sym->stack);
539       return line;
540     }
541     if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
542       strcat (line, "code");
543       return line;
544     }
545     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
546       strcat (line, "far");
547       return line;
548     }
549     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
550       strcat (line, "bit");
551       return line;
552     }
553     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
554       strcat (line, "dir");
555       return line;
556     }
557     strcat (line, "unknown");
558     return line;
559   } else if (IS_VALOP(op)) {
560     opRegName(op, 0, line, 1);
561   } else if (IS_TYPOP(op)) {
562     sprintf (line, "(");
563     if (isPtr) {
564       if (DCL_TYPE(optype)==FPOINTER)
565         strcat (line, "far * ");
566       else if (DCL_TYPE(optype)==CPOINTER)
567         strcat (line, "code * ");
568       else if (DCL_TYPE(optype)==GPOINTER)
569         strcat (line, "gen * ");
570       else if (DCL_TYPE(optype)==POINTER)
571         strcat (line, "near * ");
572       else
573         strcat (line, "unknown * ");
574     }
575     // forget about static, volatile, ... for now
576     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
577     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
578     strcat (line, nounName(operandType(op)));
579     strcat (line, ")");
580   } else {
581     bailOut("printOp: unexpected operand type");
582   }
583   return line;
584 }
585
586 void printIc (bool printToStderr, 
587               char *op, iCode * ic, bool result, bool left, bool right) {
588   char line[132];
589
590   sprintf (line, "%s(%d)", op, ic->lineno);
591   if (result) {
592     strcat (line, " result=");
593     strcat (line, printOp (IC_RESULT(ic)));
594   }
595   if (left) {
596     strcat (line, " left=");
597     strcat (line, printOp (IC_LEFT(ic)));
598   }
599   if (right) {
600     strcat (line, " right=");
601     strcat (line, printOp (IC_RIGHT(ic)));
602   }
603   emitcode (";", line);
604   if (printToStderr) {
605     fprintf (stderr, "%s\n", line);
606   }
607 }
608
609 /*-----------------------------------------------------------------*/
610 /* toBoolean - return carry for operand!=0                           */
611 /*-----------------------------------------------------------------*/
612 static char *toBoolean (operand * op) {
613   symbol *tlbl=newiTempLabel(NULL);
614
615   switch (AOP_SIZE(op)) 
616     {
617     case 1:
618     case 2:
619       emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
620                 "This needs a second thought");
621       
622       emitcode ("", "%05d$:", tlbl->key+100);
623       return "c";
624     }
625
626   bailOut("toBoolean: unknown size");
627   return NULL;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* regsInCommon - two operands have some registers in common       */
632 /*-----------------------------------------------------------------*/
633 static bool regsInCommon (operand * op1, operand * op2) {
634   symbol *sym1, *sym2;
635   int i;
636
637   /* if they have registers in common */
638   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
639     return FALSE;
640
641   sym1 = OP_SYMBOL (op1);
642   sym2 = OP_SYMBOL (op2);
643
644   if (sym1->nRegs == 0 || sym2->nRegs == 0)
645     return FALSE;
646
647   for (i = 0; i < sym1->nRegs; i++)
648     {
649       int j;
650       if (!sym1->regs[i])
651         continue;
652
653       for (j = 0; j < sym2->nRegs; j++)
654         {
655           if (!sym2->regs[j])
656             continue;
657
658           if (sym2->regs[j] == sym1->regs[i])
659             return TRUE;
660         }
661     }
662
663   return FALSE;
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* resultRemat - result  is rematerializable                       */
668 /*-----------------------------------------------------------------*/
669 static int resultRemat (iCode * ic) {
670   if (SKIP_IC (ic) || ic->op == IFX)
671     return 0;
672   
673   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
674     {
675       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
676       if (sym->remat && !POINTER_SET (ic))
677         return 1;
678     }
679   
680   return 0;
681 }
682
683 /*-----------------------------------------------------------------*/
684 /* genNot - generate code for ! operation                          */
685 /*-----------------------------------------------------------------*/
686 static void genNot (iCode * ic) {
687   printIc (0, "genNot:", ic, 1,1,0);
688 }
689
690 /*-----------------------------------------------------------------*/
691 /* genCpl - generate code for complement                           */
692 /*-----------------------------------------------------------------*/
693 static void genCpl (iCode * ic) {
694   printIc (0, "genCpl", ic, 1,1,0);
695 }
696
697 /*-----------------------------------------------------------------*/
698 /* genUminus - unary minus code generation                         */
699 /*-----------------------------------------------------------------*/
700 static void genUminus (iCode * ic) {
701   printIc (0, "genUminus", ic, 1,1,0);
702 }
703
704 /*-----------------------------------------------------------------*/
705 /* genIpush - generate code for pushing                            */
706 /*-----------------------------------------------------------------*/
707 static void genIpush (iCode * ic) {
708   operand *left=IC_LEFT(ic);
709
710   printIc (0, "genIpush", ic, 0,1,0);
711   aopOp(left,FALSE,FALSE);
712
713
714   if (AOP_TYPE(left)==AOP_LIT) {
715     switch (AOP_SIZE(left)) 
716       {
717       case 1:
718         emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
719         emitcode ("push", "r1l");
720         _G.parmsPushed++;
721         return;
722       case 2:
723         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
724         emitcode ("push", "r1");
725         _G.parmsPushed++;
726         return;
727       case 3:
728         emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
729         emitcode ("push", "r1l");
730         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
731         emitcode ("push", "r1");
732         _G.parmsPushed += 2;
733         return;
734       case 4:
735         emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
736         emitcode ("push", "r1");
737         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
738         emitcode ("push", "r1");
739         _G.parmsPushed += 2;
740         return;
741       }
742   } else {
743     if (AOP_SIZE(left)>2) {
744       emitcode ("push", "%s", AOP_NAME(left)[1]);
745       _G.parmsPushed++;
746     }
747     emitcode ("push", "%s", AOP_NAME(left)[0]);
748     _G.parmsPushed++;
749   }
750 }
751
752 /*-----------------------------------------------------------------*/
753 /* genIpop - recover the registers: can happen only for spilling   */
754 /*-----------------------------------------------------------------*/
755 static void genIpop (iCode * ic) {
756   printIc (0, "genIpop", ic, 0,1,0);
757 }
758
759 /*-----------------------------------------------------------------*/
760 /* genCall - generates a call statement                            */
761 /*-----------------------------------------------------------------*/
762 static void genCall (iCode * ic) {
763   operand *result=IC_RESULT(ic);
764
765   emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
766             OP_SYMBOL(IC_LEFT(ic))->name,
767             printOp (IC_RESULT(ic)));
768   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
769
770   /* readjust the stack if we have pushed some parms */
771   if (_G.parmsPushed) {
772     emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
773     _G.parmsPushed=0;
774   }
775
776   /* if we need to assign a result value */
777   if (IS_ITEMP (IC_RESULT(ic)) &&
778       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
779     aopOp(result,FALSE,FALSE);
780     switch (AOP_SIZE(result))
781       {
782       case 1:
783         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
784         return;
785       case 2:
786         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
787         return;
788       case 3:
789         // generic pointer
790         emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
791         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
792         return;
793       case 4:
794         emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
795         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
796         return;
797       }
798     bailOut("genCall");
799   }
800 }
801
802 /*-----------------------------------------------------------------*/
803 /* genPcall - generates a call by pointer statement                */
804 /*-----------------------------------------------------------------*/
805 static void
806 genPcall (iCode * ic)
807 {
808   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
809 }
810
811 /*-----------------------------------------------------------------*/
812 /* genFunction - generated code for function entry                 */
813 /*-----------------------------------------------------------------*/
814 static void genFunction (iCode * ic) {
815   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
816   sym_link *type=sym->type;
817
818   emitcode (";", "genFunction %s", sym->rname);
819
820   /* print the allocation information */
821   printAllocInfo (currFunc, codeOutFile);
822
823   emitcode ("", "%s:", sym->rname);
824
825   if (IFFUNC_ISNAKED(type))
826   {
827       emitcode(";", "naked function: no prologue.");
828       return;
829   }
830
831   /* adjust the stack for locals used in this function */
832   if (sym->stack) {
833     emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
834   }
835 }
836
837 /*-----------------------------------------------------------------*/
838 /* genEndFunction - generates epilogue for functions               */
839 /*-----------------------------------------------------------------*/
840 static void
841 genEndFunction (iCode * ic)
842 {
843   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
844
845   printIc (0, "genEndFunction", ic, 0,0,0);
846
847   if (IFFUNC_ISNAKED(sym->type)) {
848       emitcode(";", "naked function: no epilogue.");
849       return;
850   }
851
852   /* readjust the stock for locals used in this function */
853   if (sym->stack) {
854     emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
855   }
856
857   if (IFFUNC_ISISR(sym->type)) {
858     emitcode ("reti", "");
859   } else {
860     emitcode ("ret", "");
861   }
862 }
863
864 /*-----------------------------------------------------------------*/
865 /* genRet - generate code for return statement                     */
866 /*-----------------------------------------------------------------*/
867 static void genRet (iCode * ic) {
868
869   if (!IC_LEFT(ic)) {
870     printIc (0, "genRet", ic, 0, 0, 0);
871   } else {
872     printIc (0, "genRet", ic, 0, 1, 0);
873     aopOp(IC_LEFT(ic), TRUE, TRUE);
874     switch (AOP_SIZE(IC_LEFT(ic)))
875       {
876       case 4:
877         emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
878         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
879         break;
880       case 3:
881         emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
882         // fall through
883       case 2:
884         emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
885         break;
886       case 1:
887         emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
888         break;
889       default:
890         bailOut("genRet");
891       }
892   }
893
894   emitcode ("jmp", "%05d$", returnLabel->key+100);
895 }
896
897 /*-----------------------------------------------------------------*/
898 /* genLabel - generates a label                                    */
899 /*-----------------------------------------------------------------*/
900 static void genLabel (iCode * ic) {
901   /* special case never generate */
902   if (IC_LABEL (ic) == entryLabel)
903     return;
904
905   emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* genGoto - generates a jmp                                      */
911 /*-----------------------------------------------------------------*/
912 static void genGoto (iCode * ic) {
913   emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
914   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
915 }
916
917 /*-----------------------------------------------------------------*/
918 /* genPlus - generates code for addition                           */
919 /*-----------------------------------------------------------------*/
920 static void genPlus (iCode * ic) {
921   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
922   int size;
923   char *instr;
924
925   printIc (0, "genPlus", ic, 1,1,1);
926
927   size=aopOp(result, TRUE, TRUE);
928
929   /* if left is a literal, then exchange them */
930   if (IS_LITERAL(operandType(left))) {
931     operand *tmp = right;
932     right = left;
933     left = tmp;
934   }
935     
936   if (aopIsBit(result)) {
937     if (IS_LITERAL(operandType(right))) {
938       if (operandLitValue(right)) {
939         emitcode ("setb", AOP_NAME(result)[0]);
940         return;
941       }
942       aopOp(left, TRUE, TRUE);
943       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
944       return;
945     }
946     bailOut("genPlus: unfinished genPlus bit");
947   }
948   
949   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
950   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
951
952   // special case for "* = * + char", needs a closer look
953   // heck, this shouldn't have come here but bug-223113 does
954   if (size==3 && AOP_SIZE(right)==1) {
955     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
956     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
957     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
958     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
959     emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
960     return;
961   }
962
963   // special case for "xdata * = xdata * + char", needs a closer look
964   // heck, this shouldn't have come here but bug-441448 does
965   if (size==2 && AOP_SIZE(right)==1) {
966     emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
967     emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
968     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
969     emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
970     return;
971   }
972
973   if (size>1) {
974     instr="add.w";
975   } else {
976     instr="add.b";
977   }
978   if (!aopEqual(result->aop, left->aop, 0)) {
979     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
980   }
981   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
982   if (size>2) {
983     if (!aopEqual(result->aop, left->aop, 1)) {
984       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
985     }
986     if (size==3) {
987       // generic pointer
988     } else {
989       emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
990     }
991   }
992   return;
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* genMinus - generates code for subtraction                       */
997 /*-----------------------------------------------------------------*/
998 static void genMinus (iCode * ic) {
999   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1000   int size;
1001   char *instr;
1002
1003   printIc (0, "genMinus", ic, 1,1,1);
1004
1005   size=aopOp(result, TRUE, TRUE);
1006
1007   /* if left is a literal, then exchange them */
1008   if (IS_LITERAL(operandType(left))) {
1009     operand *tmp = right;
1010     right = left;
1011     left = tmp;
1012   }
1013     
1014   if (aopIsBit(result)) {
1015     if (IS_LITERAL(operandType(right))) {
1016       if (operandLitValue(right)) {
1017         emitcode ("clr", AOP_NAME(result)[0]);
1018         return;
1019       }
1020       aopOp(left, TRUE, TRUE);
1021       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1022       return;
1023     }
1024     bailOut("genPlus: unfinished genPlus bit");
1025   }
1026   
1027   if (isOperandEqual(result,left)) {
1028     left->aop=result->aop;
1029   } else {
1030     aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1031   }
1032   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1033
1034   if (size>1) {
1035     instr="sub.w";
1036   } else {
1037     instr="sub.b";
1038   }
1039   if (!aopEqual(result->aop, left->aop, 0)) {
1040     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1041   }
1042   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1043   if (size>2) {
1044     if (!aopEqual(result->aop, left->aop, 1)) {
1045       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1046     }
1047     if (size==3) {
1048       // generic pointer
1049     } else {
1050       emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1051     }
1052   }
1053   return;
1054 }
1055
1056 /*-----------------------------------------------------------------*/
1057 /* genMult - generates code for multiplication                     */
1058 /*-----------------------------------------------------------------*/
1059 static void genMult (iCode * ic) {
1060   printIc (0, "genMult", ic, 1,1,1);
1061 }
1062
1063 /*-----------------------------------------------------------------*/
1064 /* genDiv - generates code for division                            */
1065 /*-----------------------------------------------------------------*/
1066 static void genDiv (iCode * ic) {
1067   printIc (0, "genDiv", ic, 1,1,1);
1068 }
1069
1070 /*-----------------------------------------------------------------*/
1071 /* genMod - generates code for division                            */
1072 /*-----------------------------------------------------------------*/
1073 static void genMod (iCode * ic) {
1074   printIc (0, "genMod", ic, 1,1,1);
1075 }
1076
1077 /*-----------------------------------------------------------------*/
1078 /* ifxForOp - returns the icode containing the ifx for operand     */
1079 /*-----------------------------------------------------------------*/
1080 static iCode *ifxForOp (operand * op, iCode * ic) {
1081   /* if true symbol then needs to be assigned */
1082   if (IS_TRUE_SYMOP (op))
1083     return NULL;
1084   
1085   /* if this has register type condition and
1086      the next instruction is ifx with the same operand
1087      and live to of the operand is upto the ifx only then */
1088   if (ic->next &&
1089       ic->next->op == IFX &&
1090       IC_COND (ic->next)->key == op->key &&
1091       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1092     return ic->next;
1093   
1094   return NULL;
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* genCmp - compares whatever                                      */
1099 /*-----------------------------------------------------------------*/
1100 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1101   iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1102   operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1103   int size;
1104   bool isTrue;
1105   char *instr;
1106   int jlbl;
1107
1108
1109   size=aopOp(left, TRUE, TRUE);
1110   aopOp(right, !aopIsPtr(left), TRUE);
1111
1112   if (size==1) {
1113     instr="cmp.b";
1114   } else {
1115     instr="cmp.w";
1116   }
1117
1118   if (!ifx) {
1119     aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1120     jlbl=newiTempLabel(NULL)->key+100;
1121     emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1122     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1123     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1124     emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1125     emitcode("", "%05d$:", jlbl);
1126   } else {
1127     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1128     if (IC_TRUE(ifx)) {
1129       isTrue=TRUE;
1130       jlbl=IC_TRUE(ifx)->key+100;
1131     } else {
1132       isTrue=FALSE;
1133       jlbl=IC_FALSE(ifx)->key+100;
1134     }
1135     
1136     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1137
1138     ifx->generated=1;
1139   }
1140
1141   if (size>2) {
1142     bailOut("genCmp: size > 2");
1143   }
1144
1145 }
1146
1147 /*-----------------------------------------------------------------*/
1148 /* genCmpEq :- generates code for equal to                         */
1149 /*-----------------------------------------------------------------*/
1150 static void genCmpEq (iCode * ic) {
1151   printIc (0, "genCmpEq", ic, 0,1,1);
1152   genCmp(ic, "beq", "bne"); // no sign
1153 }
1154
1155 /*-----------------------------------------------------------------*/
1156 /* genCmpGt :- greater than comparison                             */
1157 /*-----------------------------------------------------------------*/
1158 static void genCmpGt (iCode * ic) {
1159   printIc (0, "genCmpGt", ic, 0,1,1);
1160   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1161       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1162     genCmp(ic, "bg", "bl"); // unsigned
1163   } else {
1164     genCmp(ic, "bgt", "ble"); // signed
1165   }
1166 }
1167
1168 /*-----------------------------------------------------------------*/
1169 /* genCmpLt - less than comparisons                                */
1170 /*-----------------------------------------------------------------*/
1171 static void genCmpLt (iCode * ic) {
1172   printIc (0, "genCmpLt", ic, 0,1,1);
1173   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1174       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1175     genCmp(ic, "bcs", "bcc"); // unsigned
1176   } else {
1177     genCmp(ic, "blt", "bge"); // signed
1178   }
1179 }
1180
1181 /*-----------------------------------------------------------------*/
1182 /* hasInc - operand is incremented before any other use            */
1183 /*-----------------------------------------------------------------*/
1184 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1185   sym_link *type = operandType(op);
1186   sym_link *retype = getSpec (type);
1187   iCode *lic = ic->next;
1188   int isize ;
1189   
1190   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1191   if (!IS_SYMOP(op)) return NULL;
1192
1193   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1194   if (IS_AGGREGATE(type->next)) return NULL;
1195   if (osize != (isize = getSize(type->next))) return NULL;
1196
1197   while (lic) {
1198     /* if operand of the form op = op + <sizeof *op> */
1199     if (lic->op == '+') {
1200       if (isOperandEqual(IC_LEFT(lic),op) &&
1201           //isOperandEqual(IC_RESULT(lic),op) && 
1202           isOperandLiteral(IC_RIGHT(lic)) &&
1203           operandLitValue(IC_RIGHT(lic)) == isize) {
1204         emitcode (";", "Found hasInc");
1205         return lic;
1206       }
1207     }
1208     /* if the operand used or deffed */
1209     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1210       return NULL;
1211     }
1212     /* if GOTO or IFX */
1213     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1214     lic = lic->next;
1215   }
1216   return NULL;
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* genAndOp - for && operation                                     */
1221 /*-----------------------------------------------------------------*/
1222 static void genAndOp (iCode * ic) {
1223   printIc (0, "genAndOp(&&)", ic, 1,1,1);
1224 }
1225
1226 /*-----------------------------------------------------------------*/
1227 /* genOrOp - for || operation                                      */
1228 /*-----------------------------------------------------------------*/
1229 static void genOrOp (iCode * ic) {
1230   printIc (0, "genOrOp(||)", ic, 1,1,1);
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* genAnd  - code for and                                            */
1235 /*-----------------------------------------------------------------*/
1236 static void genAnd (iCode * ic, iCode * ifx) {
1237   printIc (0, "genAnd", ic, 1,1,1);
1238 }
1239
1240 /*-----------------------------------------------------------------*/
1241 /* genOr  - code for or                                            */
1242 /*-----------------------------------------------------------------*/
1243 static void genOr (iCode * ic, iCode * ifx) {
1244   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1245   int size;
1246   char *instr;
1247
1248   printIc (0, "genOr", ic, 1,1,1);
1249
1250   size=aopOp(result, TRUE, TRUE);
1251
1252   /* if left is a literal, then exchange them */
1253   if (IS_LITERAL(operandType(left))) {
1254     operand *tmp = right;
1255     right = left;
1256     left = tmp;
1257   }
1258     
1259   if (aopIsBit(result)) {
1260     if (IS_LITERAL(operandType(right))) {
1261       if (operandLitValue(right)) {
1262         emitcode ("setb", AOP_NAME(result)[0]);
1263         return;
1264       }
1265       aopOp(left, TRUE, TRUE);
1266       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1267       return;
1268     }
1269   }
1270   
1271   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1272   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1273
1274   if (size>1) {
1275     instr="or.w";
1276   } else {
1277     instr="or.b";
1278   }
1279   if (!aopEqual(result->aop, left->aop, 0)) {
1280     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1281   }
1282   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1283   if (size>2) {
1284     if (!aopEqual(result->aop, left->aop, 1)) {
1285       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1286     }
1287     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1288   }
1289   return;
1290 }
1291
1292 /*-----------------------------------------------------------------*/
1293 /* genXor - code for xclusive or                                   */
1294 /*-----------------------------------------------------------------*/
1295 static void genXor (iCode * ic, iCode * ifx) {
1296   printIc (0, "genXor", ic, 1,1,1);
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* genInline - write the inline code out                           */
1301 /*-----------------------------------------------------------------*/
1302 static void genInline (iCode * ic) {
1303
1304   printIc (0, "genInline", ic, 0,0,0);
1305   
1306   emitcode ("", IC_INLINE(ic));
1307 }
1308
1309 /*-----------------------------------------------------------------*/
1310 /* genRRC - rotate right with carry                                */
1311 /*-----------------------------------------------------------------*/
1312 static void genRRC (iCode * ic) {
1313   printIc (0, "genRRC", ic, 1,1,0);
1314 }
1315
1316 /*-----------------------------------------------------------------*/
1317 /* genRLC - generate code for rotate left with carry               */
1318 /*-----------------------------------------------------------------*/
1319 static void genRLC (iCode * ic) {
1320   printIc (0, "genRLC", ic, 1,1,0);
1321 }
1322
1323 /*-----------------------------------------------------------------*/
1324 /* genGetHbit - generates code get highest order bit               */
1325 /*-----------------------------------------------------------------*/
1326 static void genGetHbit (iCode * ic) {
1327   printIc (0, "genGetHbit", ic, 1,1,0);
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* genLeftShift - generates code for left shifting                 */
1332 /*-----------------------------------------------------------------*/
1333 static void genLeftShift (iCode * ic) {
1334   printIc (0, "genLeftShift", ic, 1,1,1);
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* genRightShift - generate code for right shifting                */
1339 /*-----------------------------------------------------------------*/
1340 static void genRightShift (iCode * ic) {
1341   printIc (0, "genRightShift", ic, 1,1,1);
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* genPointerGet - generate code for pointer get                   */
1346 /*-----------------------------------------------------------------*/
1347 static void genPointerGet (iCode * ic, iCode *pi) {
1348   char *instr, *scratchReg;
1349   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1350   bool codePointer=IS_CODEPTR(operandType(left));
1351   int size;
1352
1353   if (pi) {
1354     printIc (0, "genPointerGet pi", ic, 1,1,0);
1355   } else {
1356     printIc (0, "genPointerGet", ic, 1,1,0);
1357   }
1358
1359   if (!IS_PTR(operandType(left))) {
1360     bailOut ("genPointerGet: pointer required");
1361   }
1362
1363   aopOp(left,FALSE,FALSE);
1364   size=aopOp(result,TRUE,aopIsDir(left));
1365
1366   if (IS_GENPTR(operandType(left))) {
1367     symbol *tlbl1=newiTempLabel(NULL);
1368     symbol *tlbl2=newiTempLabel(NULL);
1369     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1370     emitcode ("beq", "%05d$", tlbl1->key+100);
1371     // far/near pointer
1372     if (pi) {
1373       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1374       pi->generated=1;
1375     } else {
1376       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1377     }
1378     if (size>2) {
1379       if (pi) {
1380         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1381       } else {
1382         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1383       }
1384     }
1385     emitcode ("br", "%05d$", tlbl2->key+100);
1386     emitcode ("", "%05d$:", tlbl1->key+100);
1387     // code pointer
1388     if (pi) {
1389       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1390       pi->generated=1;
1391     } else {
1392       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1393       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1394     }
1395     if (size>2) {
1396       if (pi) {
1397         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1398       } else {
1399         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1400       }
1401     }
1402     emitcode ("", "%05d$:", tlbl2->key+100);
1403     return;
1404   }
1405
1406   switch (AOP_TYPE(left)) 
1407     {
1408     case AOP_LIT:
1409       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1410       sprintf (AOP_NAME(left)[0], "r1");
1411       // fall through
1412     case AOP_REG:
1413       if (size>1) {
1414         if (codePointer) {
1415           instr=MOVCW;
1416         } else {
1417           instr=MOVW;
1418         }
1419         scratchReg=R1;
1420       } else {
1421         if (codePointer) {
1422           instr=MOVCB;
1423         } else {
1424           instr=MOVB;
1425         }
1426         scratchReg=R1L;
1427       }
1428       if (AOP_TYPE(result)==AOP_STK) {
1429         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1430         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1431       } else {
1432         if (pi) {
1433           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1434                     AOP_NAME(left)[0]);
1435           pi->generated=1;
1436         } else {
1437           if (codePointer) {
1438             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1439             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1440           } else {
1441             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1442                       AOP_NAME(left)[0]);
1443           }
1444         }
1445       }
1446       if (size > 2) {
1447         if (size==3) {
1448           if (codePointer) {
1449             instr=MOVCB;
1450           } else {
1451             instr=MOVB;
1452           }
1453           scratchReg=R1L;
1454         }
1455         if (AOP_TYPE(result)==AOP_STK) {
1456           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1457           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1458         } else {
1459           if (pi) {
1460             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1461                       AOP_NAME(left)[0]);
1462           } else {
1463             if (codePointer) {
1464               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1465             } else {
1466               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1467                         AOP_NAME(left)[0]);
1468             }
1469           }
1470         }
1471       }
1472       return;
1473     }
1474   bailOut ("genPointerGet");
1475 }
1476
1477 /*-----------------------------------------------------------------*/
1478 /* genPointerSet - stores the value into a pointer location        */
1479 /*-----------------------------------------------------------------*/
1480 static void genPointerSet (iCode * ic, iCode *pi) {
1481   char *instr;
1482   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1483   int size;
1484
1485   printIc (0, "genPointerSet", ic, 1,0,1);
1486
1487   if (!IS_PTR(operandType(result))) {
1488     bailOut ("genPointerSet: pointer required");
1489   }
1490
1491   aopOp(result,FALSE,FALSE);
1492   size=aopOp(right,FALSE, FALSE);
1493
1494   if (IS_GENPTR(operandType(result))) {
1495     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1496               AOP_NAME(result)[0], AOP_NAME(result)[1],
1497               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1498     return;
1499   }
1500
1501   switch (AOP_TYPE(right)) 
1502     {
1503     case AOP_LIT:
1504     case AOP_REG:
1505       if (size>1) {
1506         instr=MOVW;
1507       } else {
1508         instr=MOVB;
1509       }
1510       if (pi) {
1511         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1512         pi->generated=1;
1513       } else {
1514         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1515       }
1516       if (size > 2) {
1517         if (size==3) {
1518           instr=MOVB;
1519         }
1520         if (pi) {
1521           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1522                     AOP_NAME(right)[1]);
1523         } else {
1524           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1525                     AOP_NAME(right)[1]);
1526         }
1527       }
1528       return;
1529     }
1530   bailOut ("genPointerSet");
1531 }
1532
1533 /*-----------------------------------------------------------------*/
1534 /* genIfx - generate code for Ifx statement                        */
1535 /*-----------------------------------------------------------------*/
1536 static void genIfx (iCode * ic, iCode * popIc) {
1537   int size;
1538   char *instr;
1539   bool trueOrFalse;
1540   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1541   operand *cond=IC_COND(ic);
1542
1543   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1544             ic->lineno, printOp(cond),
1545             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1546             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1547
1548   size=aopOp(cond,TRUE,TRUE);
1549
1550   if (IC_TRUE(ic)) {
1551     trueOrFalse=TRUE;
1552     jlbl=IC_TRUE(ic);
1553   } else {
1554     trueOrFalse=FALSE;
1555     jlbl=IC_FALSE(ic);
1556   }
1557
1558   switch (AOP_TYPE(cond) )
1559     {
1560     case AOP_BIT:
1561       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1562                 AOP_NAME(cond)[0], tlbl->key+100);
1563       emitcode ("jmp", "%05d$", jlbl->key+100);
1564       emitcode ("", "%05d$:", tlbl->key+100);
1565       return;
1566     case AOP_REG:
1567     case AOP_DIR:
1568     case AOP_FAR:
1569     case AOP_STK:
1570       if (size>1) {
1571         instr="cmp.w";
1572       } else {
1573         instr="cmp.b";
1574       }
1575       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1576       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1577       if (size > 2) {
1578         if (size==3) {
1579           // generic pointer, forget the generic part
1580         } else {
1581           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1582           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1583         }
1584       }
1585       emitcode ("jmp", "%05d$", jlbl->key+100);
1586       emitcode ("", "%05d$:", tlbl->key+100);
1587       return;
1588     }
1589   bailOut ("genIfx");
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* genAddrOf - generates code for address of                       */
1594 /*-----------------------------------------------------------------*/
1595 static void genAddrOf (iCode * ic) {
1596   int size;
1597   operand *left=IC_LEFT(ic);
1598
1599   printIc (0, "genAddrOf", ic, 1,1,0);
1600
1601   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1602
1603   if (isOperandOnStack(left)) {
1604     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1605               getStackOffset(OP_SYMBOL(left)->stack));
1606     if (size > 2) {
1607       // this must be a generic pointer
1608       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1609     }
1610     return;
1611   }
1612
1613   if (isOperandInDirSpace(left) ||
1614       isOperandInFarSpace(left) ||
1615       isOperandInCodeSpace(left)) {
1616     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1617               OP_SYMBOL(left)->rname);
1618     if (size > 2) {
1619       // this must be a generic pointer
1620       int space=0; // dir space
1621       if (isOperandInFarSpace(left)) {
1622         space=1;
1623       } else if (isOperandInCodeSpace(left)) {
1624         space=2;
1625       }
1626       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1627     }
1628     return;
1629   }
1630
1631   bailOut("genAddrOf");
1632 }
1633
1634 /*-----------------------------------------------------------------*/
1635 /* genAssign - generate code for assignment                        */
1636 /*-----------------------------------------------------------------*/
1637 static void genAssign (iCode * ic) {
1638   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1639   int size;
1640   char *instr;
1641
1642   printIc (0, "genAssign", ic, 1,0,1);
1643   
1644   if (!IS_SYMOP(result)) {
1645     bailOut("genAssign: result is not a symbol");
1646   }
1647   
1648   aopOp(result, TRUE, TRUE);
1649   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1650   size=AOP_SIZE(result);
1651
1652   /* if result is a bit */
1653   if (AOP_TYPE(result) == AOP_BIT) {
1654     /* if right is literal, we know what the value is */
1655     if (AOP_TYPE(right) == AOP_LIT) {
1656       if (operandLitValue(right)) {
1657         emitcode ("setb", AOP_NAME(result)[0]);
1658       } else {
1659         emitcode ("clr", AOP_NAME(result)[0]);
1660       }
1661       return;
1662     }
1663     /* if right is also a bit */
1664     if (AOP_TYPE(right) == AOP_BIT) {
1665       emitcode ("mov", "c,%s", AOP_NAME(right));
1666       emitcode ("mov", "%s,c", AOP_NAME(result));
1667       return;
1668     }
1669     /* we need to or */
1670     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1671     return;
1672   }
1673
1674   // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1675   /* general case */
1676   if (size>1) {
1677     instr=MOVW;
1678   } else {
1679     instr=MOVB;
1680   }
1681   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1682
1683   if (size > 2) {
1684     if (size==3) {
1685       // generic pointer
1686       instr=MOVB;
1687     }
1688     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1689     return;
1690   }
1691 }
1692
1693 /*-----------------------------------------------------------------*/
1694 /* genJumpTab - genrates code for jump table                       */
1695 /*-----------------------------------------------------------------*/
1696 static void genJumpTab (iCode * ic) {
1697   printIc (0, "genJumpTab", ic, 0,0,0);
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* genCast - gen code for casting                                  */
1702 /*-----------------------------------------------------------------*/
1703 static void genCast (iCode * ic) {
1704   int size;
1705   operand *result=IC_RESULT(ic);
1706   operand *right=IC_RIGHT(ic);
1707   sym_link *ctype=operandType(IC_LEFT(ic));
1708   sym_link *rtype=operandType(IC_RIGHT(ic));
1709   sym_link *etype=getSpec(rtype);
1710   short ptrType, signedness;
1711
1712   printIc (0, "genCast", ic, 1,1,1);
1713
1714   aopOp(result, TRUE, TRUE);
1715   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1716   size=AOP_SIZE(result);
1717   
1718   /* if result is a bit */
1719   if (AOP_TYPE(result) == AOP_BIT) {
1720     /* if right is literal, we know what the value is */
1721     if (AOP_TYPE(right) == AOP_LIT) {
1722       if (operandLitValue(right)) {
1723         emitcode ("setb", AOP_NAME(result)[0]);
1724       } else {
1725         emitcode ("clr", AOP_NAME(result)[0]);
1726       }
1727       return;
1728     }
1729     /* if right is also a bit */
1730     if (AOP_TYPE(right) == AOP_BIT) {
1731       emitcode ("mov", "c,%s", AOP_NAME(right));
1732       emitcode ("mov", "%s,c", AOP_NAME(result));
1733       return;
1734     }
1735     /* we need to or */
1736     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1737     return;
1738   }
1739
1740   /* if right is a bit */
1741   if (AOP_TYPE(right)==AOP_BIT) {
1742     emitcode ("mov", "c,%s", AOP_NAME(right));
1743     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1744     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1745     if (size>2) {
1746       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1747     }
1748     return;
1749   }
1750
1751   /* if the result is of type pointer */
1752   if (IS_PTR (ctype)) {
1753
1754     if (AOP_SIZE(right)>1) {
1755       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1756     } else {
1757       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1758       emitcode ("sext", "r1h");
1759       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1760     }
1761     
1762     /* if pointer to generic pointer */
1763     if (IS_GENPTR (ctype)) {
1764             
1765       if (IS_GENPTR (rtype)) {
1766         bailOut("genCast: gptr -> gptr");
1767       }
1768
1769       if (IS_PTR (rtype)) {
1770         ptrType = DCL_TYPE (rtype);
1771       } else {
1772         /* we have to go by the storage class */
1773         if (!SPEC_OCLS(etype)) {
1774           ptrType=0; // hush the compiler
1775           bailOut("genCast: unknown storage class");
1776         } else {
1777           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1778         }
1779       }
1780       
1781       /* the generic part depends on the type */
1782       switch (ptrType)
1783         {
1784         case POINTER:
1785           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1786           break;
1787         case FPOINTER:
1788           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1789           break;
1790         case CPOINTER:
1791           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1792           break;
1793         default:
1794           bailOut("genCast: got unknown storage class");
1795         }
1796     }
1797     return;
1798   }
1799
1800   /* do we have to sign extend? */
1801   signedness = SPEC_USIGN(rtype);
1802
1803   /* now depending on the size */
1804   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1805     {
1806     case 0x44:
1807     case 0x33:
1808       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1809       // fall through
1810     case 0x24:
1811     case 0x22:
1812     case 0x11:
1813       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1814       return;
1815     case 0x42:
1816       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1817       if (signedness) {
1818         emitcode("sext", "%s", AOP_NAME(result)[1]);
1819       } else {
1820         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1821       }
1822       return;
1823     case 0x41:
1824     case 0x21:
1825       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1826       if (signedness) {
1827         emitcode("sext", "r1h");
1828       } else {
1829         emitcode("mov", "r1h,#0");
1830       }
1831       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1832       if (size==2)
1833         return;
1834       // fall through: case 0x41
1835       if (signedness) {
1836         emitcode("sext", "r1");
1837       } else {
1838         emitcode("mov", "r1,#0");
1839       }
1840       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1841       return;
1842     case 0x14:
1843     case 0x12:
1844       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1845       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1846       return;
1847     }
1848   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1849           AOP_SIZE(result), AOP_SIZE(right));
1850   bailOut("genCast: unknown size");
1851 }
1852
1853
1854 /*-----------------------------------------------------------------*/
1855 /* genDjnz - generate decrement & jump if not zero instrucion      */
1856 /*-----------------------------------------------------------------*/
1857 static bool genDjnz (iCode * ic, iCode * ifx) {
1858   symbol *lbl, *lbl1;
1859
1860   if (!ifx)
1861     return 0;
1862
1863   /* if the if condition has a false label
1864      then we cannot save */
1865   if (IC_FALSE (ifx))
1866     return 0;
1867
1868   /* if the minus is not of the form
1869      a = a - 1 */
1870   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1871       !IS_OP_LITERAL (IC_RIGHT (ic)))
1872     return 0;
1873
1874   if (operandLitValue (IC_RIGHT (ic)) != 1)
1875     return 0;
1876
1877   /* if the size of this greater than two then no
1878      saving */
1879   if (getSize (operandType (IC_RESULT (ic))) > 2)
1880     return 0;
1881
1882   printIc (0, "genDjnz", ic, 1,1,1);
1883
1884   /* otherwise we can save BIG */
1885   lbl = newiTempLabel (NULL);
1886   lbl1 = newiTempLabel (NULL);
1887
1888   aopOp (IC_RESULT (ic), FALSE, TRUE);
1889
1890   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1891     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1892     emitcode ("br", "%05d$", lbl1->key + 100);
1893     emitcode ("", "%05d$:", lbl->key + 100);
1894     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1895     emitcode ("", "%05d$:", lbl1->key + 100);
1896     return TRUE;
1897   }
1898
1899   bailOut("genDjnz: aop type");
1900   return FALSE;
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* genReceive - generate code for a receive iCode                  */
1905 /*-----------------------------------------------------------------*/
1906 static void genReceive (iCode * ic) {
1907   printIc (0, "genReceive", ic, 1,0,0);
1908 }
1909
1910 /*-----------------------------------------------------------------*/
1911 /* gen51Code - generate code for 8051 based controllers            */
1912 /*-----------------------------------------------------------------*/
1913 void genXA51Code (iCode * lic) {
1914   iCode *ic;
1915   int cln = 0;
1916   
1917   lineHead = lineCurr = NULL;
1918   
1919   /* if debug information required */
1920   if (options.debug && currFunc)
1921     {
1922       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1923       _G.debugLine = 1;
1924       if (IS_STATIC (currFunc->etype))
1925         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1926       else
1927         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1928       _G.debugLine = 0;
1929     }
1930   
1931   for (ic = lic; ic; ic = ic->next) {
1932     if (ic->lineno && cln != ic->lineno) {
1933       if (options.debug) {
1934         _G.debugLine = 1;
1935         emitcode ("", "C$%s$%d$%d$%d ==.",
1936                   FileBaseName (ic->filename), ic->lineno,
1937                   ic->level, ic->block);
1938         _G.debugLine = 0;
1939       }
1940       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1941                 printCLine(ic->filename, ic->lineno));
1942       cln = ic->lineno;
1943     }
1944     /* if the result is marked as
1945        spilt and rematerializable or code for
1946        this has already been generated then
1947        do nothing */
1948     if (resultRemat (ic) || ic->generated)
1949       continue;
1950     
1951     /* depending on the operation */
1952     switch (ic->op)
1953       {
1954       case '!':
1955         genNot (ic);
1956         break;
1957         
1958       case '~':
1959         genCpl (ic);
1960         break;
1961         
1962       case UNARYMINUS:
1963         genUminus (ic);
1964         break;
1965         
1966       case IPUSH:
1967         genIpush (ic);
1968         break;
1969         
1970       case IPOP:
1971         /* IPOP happens only when trying to restore a
1972            spilt live range, if there is an ifx statement
1973            following this pop then the if statement might
1974            be using some of the registers being popped which
1975            would destory the contents of the register so
1976            we need to check for this condition and handle it */
1977         if (ic->next &&
1978             ic->next->op == IFX &&
1979             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1980           genIfx (ic->next, ic);
1981         else
1982           genIpop (ic);
1983         break;
1984         
1985       case CALL:
1986         genCall (ic);
1987         break;
1988         
1989       case PCALL:
1990         genPcall (ic);
1991         break;
1992         
1993       case FUNCTION:
1994         genFunction (ic);
1995         break;
1996         
1997       case ENDFUNCTION:
1998         genEndFunction (ic);
1999         break;
2000         
2001       case RETURN:
2002         genRet (ic);
2003         break;
2004         
2005       case LABEL:
2006         genLabel (ic);
2007         break;
2008         
2009       case GOTO:
2010         genGoto (ic);
2011         break;
2012         
2013       case '+':
2014         genPlus (ic);
2015         break;
2016         
2017       case '-':
2018         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2019           genMinus (ic);
2020         break;
2021         
2022       case '*':
2023         genMult (ic);
2024         break;
2025         
2026       case '/':
2027         genDiv (ic);
2028         break;
2029         
2030       case '%':
2031         genMod (ic);
2032         break;
2033         
2034       case '>':
2035         genCmpGt (ic);
2036         break;
2037         
2038       case '<':
2039         genCmpLt (ic);
2040         break;
2041         
2042       case LE_OP:
2043       case GE_OP:
2044       case NE_OP:
2045
2046         /* note these two are xlated by algebraic equivalence
2047            during parsing SDCC.y */
2048         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2049                 "got '>=' or '<=' shouldn't have come here");
2050         break;
2051
2052       case EQ_OP:
2053         genCmpEq (ic);
2054         break;
2055         
2056       case AND_OP:
2057         genAndOp (ic);
2058         break;
2059         
2060       case OR_OP:
2061         genOrOp (ic);
2062         break;
2063         
2064       case '^':
2065         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2066         break;
2067         
2068       case '|':
2069         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2070         break;
2071         
2072       case BITWISEAND:
2073         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2074         break;
2075         
2076       case INLINEASM:
2077         genInline (ic);
2078         break;
2079         
2080       case RRC:
2081         genRRC (ic);
2082         break;
2083         
2084       case RLC:
2085         genRLC (ic);
2086         break;
2087         
2088       case GETHBIT:
2089         genGetHbit (ic);
2090         break;
2091         
2092       case LEFT_OP:
2093         genLeftShift (ic);
2094         break;
2095         
2096       case RIGHT_OP:
2097         genRightShift (ic);
2098         break;
2099         
2100       case GET_VALUE_AT_ADDRESS:
2101         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2102         break;
2103         
2104       case '=':
2105         if (POINTER_SET (ic))
2106           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2107         else
2108           genAssign (ic);
2109         break;
2110         
2111       case IFX:
2112         genIfx (ic, NULL);
2113         break;
2114         
2115       case ADDRESS_OF:
2116         genAddrOf (ic);
2117         break;
2118         
2119       case JUMPTABLE:
2120         genJumpTab (ic);
2121         break;
2122         
2123       case CAST:
2124         genCast (ic);
2125         break;
2126         
2127       case RECEIVE:
2128         genReceive (ic);
2129         break;
2130         
2131       case SEND:
2132         addSet (&_G.sendSet, ic);
2133         break;
2134         
2135       default:
2136         ic = ic;
2137       }
2138   }
2139   
2140   
2141   /* now we are ready to call the
2142      peep hole optimizer */
2143   if (!options.nopeep)
2144     peepHole (&lineHead);
2145   
2146   /* now do the actual printing */
2147   printLine (lineHead, codeOutFile);
2148   return;
2149 }