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