new options: --no-c-code-in-asm and --i-code-in-asm
[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 (IC_TRUE(ifx)) {
1119     isTrue=TRUE;
1120     jlbl=IC_TRUE(ifx)->key+100;
1121   } else {
1122     isTrue=FALSE;
1123     jlbl=IC_FALSE(ifx)->key+100;
1124   }
1125   
1126   if (!ifx) {
1127     aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1128     jlbl=newiTempLabel(NULL)->key+100;
1129     emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1130     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1131     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1132     emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1133     emitcode("", "%05d$:", jlbl);
1134   } else {
1135     emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1136     emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1137     ifx->generated=1;
1138   }
1139
1140   if (size>2) {
1141     bailOut("genCmp: size > 2");
1142   }
1143
1144 }
1145
1146 /*-----------------------------------------------------------------*/
1147 /* genCmpEq :- generates code for equal to                         */
1148 /*-----------------------------------------------------------------*/
1149 static void genCmpEq (iCode * ic) {
1150   printIc (0, "genCmpEq", ic, 0,1,1);
1151   genCmp(ic, "beq", "bne"); // no sign
1152 }
1153
1154 /*-----------------------------------------------------------------*/
1155 /* genCmpGt :- greater than comparison                             */
1156 /*-----------------------------------------------------------------*/
1157 static void genCmpGt (iCode * ic) {
1158   printIc (0, "genCmpGt", ic, 0,1,1);
1159   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1160       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1161     genCmp(ic, "bg", "bl"); // unsigned
1162   } else {
1163     genCmp(ic, "bgt", "ble"); // signed
1164   }
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* genCmpLt - less than comparisons                                */
1169 /*-----------------------------------------------------------------*/
1170 static void genCmpLt (iCode * ic) {
1171   printIc (0, "genCmpLt", ic, 0,1,1);
1172   if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1173       SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1174     genCmp(ic, "bcs", "bcc"); // unsigned
1175   } else {
1176     genCmp(ic, "blt", "bge"); // signed
1177   }
1178 }
1179
1180 /*-----------------------------------------------------------------*/
1181 /* hasInc - operand is incremented before any other use            */
1182 /*-----------------------------------------------------------------*/
1183 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1184   sym_link *type = operandType(op);
1185   sym_link *retype = getSpec (type);
1186   iCode *lic = ic->next;
1187   int isize ;
1188   
1189   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1190   if (!IS_SYMOP(op)) return NULL;
1191
1192   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1193   if (IS_AGGREGATE(type->next)) return NULL;
1194   if (osize != (isize = getSize(type->next))) return NULL;
1195
1196   while (lic) {
1197     /* if operand of the form op = op + <sizeof *op> */
1198     if (lic->op == '+') {
1199       if (isOperandEqual(IC_LEFT(lic),op) &&
1200           //isOperandEqual(IC_RESULT(lic),op) && 
1201           isOperandLiteral(IC_RIGHT(lic)) &&
1202           operandLitValue(IC_RIGHT(lic)) == isize) {
1203         emitcode (";", "Found hasInc");
1204         return lic;
1205       }
1206     }
1207     /* if the operand used or deffed */
1208     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1209       return NULL;
1210     }
1211     /* if GOTO or IFX */
1212     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1213     lic = lic->next;
1214   }
1215   return NULL;
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* genAndOp - for && operation                                     */
1220 /*-----------------------------------------------------------------*/
1221 static void genAndOp (iCode * ic) {
1222   printIc (0, "genAndOp(&&)", ic, 1,1,1);
1223 }
1224
1225 /*-----------------------------------------------------------------*/
1226 /* genOrOp - for || operation                                      */
1227 /*-----------------------------------------------------------------*/
1228 static void genOrOp (iCode * ic) {
1229   printIc (0, "genOrOp(||)", ic, 1,1,1);
1230 }
1231
1232 /*-----------------------------------------------------------------*/
1233 /* genAnd  - code for and                                            */
1234 /*-----------------------------------------------------------------*/
1235 static void genAnd (iCode * ic, iCode * ifx) {
1236   printIc (0, "genAnd", ic, 1,1,1);
1237 }
1238
1239 /*-----------------------------------------------------------------*/
1240 /* genOr  - code for or                                            */
1241 /*-----------------------------------------------------------------*/
1242 static void genOr (iCode * ic, iCode * ifx) {
1243   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1244   int size;
1245   char *instr;
1246
1247   printIc (0, "genOr", ic, 1,1,1);
1248
1249   size=aopOp(result, TRUE, TRUE);
1250
1251   /* if left is a literal, then exchange them */
1252   if (IS_LITERAL(operandType(left))) {
1253     operand *tmp = right;
1254     right = left;
1255     left = tmp;
1256   }
1257     
1258   if (aopIsBit(result)) {
1259     if (IS_LITERAL(operandType(right))) {
1260       if (operandLitValue(right)) {
1261         emitcode ("setb", AOP_NAME(result)[0]);
1262         return;
1263       }
1264       aopOp(left, TRUE, TRUE);
1265       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1266       return;
1267     }
1268   }
1269   
1270   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1271   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1272
1273   if (size>1) {
1274     instr="or.w";
1275   } else {
1276     instr="or.b";
1277   }
1278   if (!aopEqual(result->aop, left->aop, 0)) {
1279     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1280   }
1281   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1282   if (size>2) {
1283     if (!aopEqual(result->aop, left->aop, 1)) {
1284       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1285     }
1286     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1287   }
1288   return;
1289 }
1290
1291 /*-----------------------------------------------------------------*/
1292 /* genXor - code for xclusive or                                   */
1293 /*-----------------------------------------------------------------*/
1294 static void genXor (iCode * ic, iCode * ifx) {
1295   printIc (0, "genXor", ic, 1,1,1);
1296 }
1297
1298 /*-----------------------------------------------------------------*/
1299 /* genInline - write the inline code out                           */
1300 /*-----------------------------------------------------------------*/
1301 static void genInline (iCode * ic) {
1302
1303   printIc (0, "genInline", ic, 0,0,0);
1304   
1305   emitcode ("", IC_INLINE(ic));
1306 }
1307
1308 /*-----------------------------------------------------------------*/
1309 /* genRRC - rotate right with carry                                */
1310 /*-----------------------------------------------------------------*/
1311 static void genRRC (iCode * ic) {
1312   printIc (0, "genRRC", ic, 1,1,0);
1313 }
1314
1315 /*-----------------------------------------------------------------*/
1316 /* genRLC - generate code for rotate left with carry               */
1317 /*-----------------------------------------------------------------*/
1318 static void genRLC (iCode * ic) {
1319   printIc (0, "genRLC", ic, 1,1,0);
1320 }
1321
1322 /*-----------------------------------------------------------------*/
1323 /* genGetHbit - generates code get highest order bit               */
1324 /*-----------------------------------------------------------------*/
1325 static void genGetHbit (iCode * ic) {
1326   printIc (0, "genGetHbit", ic, 1,1,0);
1327 }
1328
1329 /*-----------------------------------------------------------------*/
1330 /* genLeftShift - generates code for left shifting                 */
1331 /*-----------------------------------------------------------------*/
1332 static void genLeftShift (iCode * ic) {
1333   printIc (0, "genLeftShift", ic, 1,1,1);
1334 }
1335
1336 /*-----------------------------------------------------------------*/
1337 /* genRightShift - generate code for right shifting                */
1338 /*-----------------------------------------------------------------*/
1339 static void genRightShift (iCode * ic) {
1340   printIc (0, "genRightShift", ic, 1,1,1);
1341 }
1342
1343 /*-----------------------------------------------------------------*/
1344 /* genPointerGet - generate code for pointer get                   */
1345 /*-----------------------------------------------------------------*/
1346 static void genPointerGet (iCode * ic, iCode *pi) {
1347   char *instr, *scratchReg;
1348   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1349   bool codePointer=IS_CODEPTR(operandType(left));
1350   int size;
1351
1352   if (pi) {
1353     printIc (0, "genPointerGet pi", ic, 1,1,0);
1354   } else {
1355     printIc (0, "genPointerGet", ic, 1,1,0);
1356   }
1357
1358   if (!IS_PTR(operandType(left))) {
1359     bailOut ("genPointerGet: pointer required");
1360   }
1361
1362   aopOp(left,FALSE,FALSE);
1363   size=aopOp(result,TRUE,aopIsDir(left));
1364
1365   if (IS_GENPTR(operandType(left))) {
1366     symbol *tlbl1=newiTempLabel(NULL);
1367     symbol *tlbl2=newiTempLabel(NULL);
1368     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1369     emitcode ("beq", "%05d$", tlbl1->key+100);
1370     // far/near pointer
1371     if (pi) {
1372       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1373       pi->generated=1;
1374     } else {
1375       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1376     }
1377     if (size>2) {
1378       if (pi) {
1379         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1380       } else {
1381         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1382       }
1383     }
1384     emitcode ("br", "%05d$", tlbl2->key+100);
1385     emitcode ("", "%05d$:", tlbl1->key+100);
1386     // code pointer
1387     if (pi) {
1388       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1389       pi->generated=1;
1390     } else {
1391       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1392       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1393     }
1394     if (size>2) {
1395       if (pi) {
1396         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1397       } else {
1398         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1399       }
1400     }
1401     emitcode ("", "%05d$:", tlbl2->key+100);
1402     return;
1403   }
1404
1405   switch (AOP_TYPE(left)) 
1406     {
1407     case AOP_LIT:
1408       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1409       sprintf (AOP_NAME(left)[0], "r1");
1410       // fall through
1411     case AOP_REG:
1412       if (size>1) {
1413         if (codePointer) {
1414           instr=MOVCW;
1415         } else {
1416           instr=MOVW;
1417         }
1418         scratchReg=R1;
1419       } else {
1420         if (codePointer) {
1421           instr=MOVCB;
1422         } else {
1423           instr=MOVB;
1424         }
1425         scratchReg=R1L;
1426       }
1427       if (AOP_TYPE(result)==AOP_STK) {
1428         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1429         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1430       } else {
1431         if (pi) {
1432           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1433                     AOP_NAME(left)[0]);
1434           pi->generated=1;
1435         } else {
1436           if (codePointer) {
1437             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1438             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1439           } else {
1440             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1441                       AOP_NAME(left)[0]);
1442           }
1443         }
1444       }
1445       if (size > 2) {
1446         if (size==3) {
1447           if (codePointer) {
1448             instr=MOVCB;
1449           } else {
1450             instr=MOVB;
1451           }
1452           scratchReg=R1L;
1453         }
1454         if (AOP_TYPE(result)==AOP_STK) {
1455           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1456           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1457         } else {
1458           if (pi) {
1459             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1460                       AOP_NAME(left)[0]);
1461           } else {
1462             if (codePointer) {
1463               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1464             } else {
1465               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1466                         AOP_NAME(left)[0]);
1467             }
1468           }
1469         }
1470       }
1471       return;
1472     }
1473   bailOut ("genPointerGet");
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* genPointerSet - stores the value into a pointer location        */
1478 /*-----------------------------------------------------------------*/
1479 static void genPointerSet (iCode * ic, iCode *pi) {
1480   char *instr;
1481   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1482   int size;
1483
1484   printIc (0, "genPointerSet", ic, 1,0,1);
1485
1486   if (!IS_PTR(operandType(result))) {
1487     bailOut ("genPointerSet: pointer required");
1488   }
1489
1490   aopOp(result,FALSE,FALSE);
1491   size=aopOp(right,FALSE, FALSE);
1492
1493   if (IS_GENPTR(operandType(result))) {
1494     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1495               AOP_NAME(result)[0], AOP_NAME(result)[1],
1496               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1497     return;
1498   }
1499
1500   switch (AOP_TYPE(right)) 
1501     {
1502     case AOP_LIT:
1503     case AOP_REG:
1504       if (size>1) {
1505         instr=MOVW;
1506       } else {
1507         instr=MOVB;
1508       }
1509       if (pi) {
1510         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1511         pi->generated=1;
1512       } else {
1513         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1514       }
1515       if (size > 2) {
1516         if (size==3) {
1517           instr=MOVB;
1518         }
1519         if (pi) {
1520           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1521                     AOP_NAME(right)[1]);
1522         } else {
1523           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1524                     AOP_NAME(right)[1]);
1525         }
1526       }
1527       return;
1528     }
1529   bailOut ("genPointerSet");
1530 }
1531
1532 /*-----------------------------------------------------------------*/
1533 /* genIfx - generate code for Ifx statement                        */
1534 /*-----------------------------------------------------------------*/
1535 static void genIfx (iCode * ic, iCode * popIc) {
1536   int size;
1537   char *instr;
1538   bool trueOrFalse;
1539   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1540   operand *cond=IC_COND(ic);
1541
1542   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1543             ic->lineno, printOp(cond),
1544             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1545             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1546
1547   size=aopOp(cond,TRUE,TRUE);
1548
1549   if (IC_TRUE(ic)) {
1550     trueOrFalse=TRUE;
1551     jlbl=IC_TRUE(ic);
1552   } else {
1553     trueOrFalse=FALSE;
1554     jlbl=IC_FALSE(ic);
1555   }
1556
1557   switch (AOP_TYPE(cond) )
1558     {
1559     case AOP_BIT:
1560       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1561                 AOP_NAME(cond)[0], tlbl->key+100);
1562       emitcode ("jmp", "%05d$", jlbl->key+100);
1563       emitcode ("", "%05d$:", tlbl->key+100);
1564       return;
1565     case AOP_REG:
1566     case AOP_DIR:
1567     case AOP_FAR:
1568     case AOP_STK:
1569       if (size>1) {
1570         instr="cmp.w";
1571       } else {
1572         instr="cmp.b";
1573       }
1574       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1575       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1576       if (size > 2) {
1577         if (size==3) {
1578           // generic pointer, forget the generic part
1579         } else {
1580           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1581           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1582         }
1583       }
1584       emitcode ("jmp", "%05d$", jlbl->key+100);
1585       emitcode ("", "%05d$:", tlbl->key+100);
1586       return;
1587     }
1588   bailOut ("genIfx");
1589 }
1590
1591 /*-----------------------------------------------------------------*/
1592 /* genAddrOf - generates code for address of                       */
1593 /*-----------------------------------------------------------------*/
1594 static void genAddrOf (iCode * ic) {
1595   int size;
1596   operand *left=IC_LEFT(ic);
1597
1598   printIc (0, "genAddrOf", ic, 1,1,0);
1599
1600   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1601
1602   if (isOperandOnStack(left)) {
1603     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1604               getStackOffset(OP_SYMBOL(left)->stack));
1605     if (size > 2) {
1606       // this must be a generic pointer
1607       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1608     }
1609     return;
1610   }
1611
1612   if (isOperandInDirSpace(left) ||
1613       isOperandInFarSpace(left) ||
1614       isOperandInCodeSpace(left)) {
1615     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1616               OP_SYMBOL(left)->rname);
1617     if (size > 2) {
1618       // this must be a generic pointer
1619       int space=0; // dir space
1620       if (isOperandInFarSpace(left)) {
1621         space=1;
1622       } else if (isOperandInCodeSpace(left)) {
1623         space=2;
1624       }
1625       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1626     }
1627     return;
1628   }
1629
1630   bailOut("genAddrOf");
1631 }
1632
1633 /*-----------------------------------------------------------------*/
1634 /* genAssign - generate code for assignment                        */
1635 /*-----------------------------------------------------------------*/
1636 static void genAssign (iCode * ic) {
1637   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1638   int size;
1639   char *instr;
1640
1641   printIc (0, "genAssign", ic, 1,0,1);
1642   
1643   if (!IS_SYMOP(result)) {
1644     bailOut("genAssign: result is not a symbol");
1645   }
1646   
1647   aopOp(result, TRUE, TRUE);
1648   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1649   size=AOP_SIZE(result);
1650
1651   /* if result is a bit */
1652   if (AOP_TYPE(result) == AOP_BIT) {
1653     /* if right is literal, we know what the value is */
1654     if (AOP_TYPE(right) == AOP_LIT) {
1655       if (operandLitValue(right)) {
1656         emitcode ("setb", AOP_NAME(result)[0]);
1657       } else {
1658         emitcode ("clr", AOP_NAME(result)[0]);
1659       }
1660       return;
1661     }
1662     /* if right is also a bit */
1663     if (AOP_TYPE(right) == AOP_BIT) {
1664       emitcode ("mov", "c,%s", AOP_NAME(right));
1665       emitcode ("mov", "%s,c", AOP_NAME(result));
1666       return;
1667     }
1668     /* we need to or */
1669     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1670     return;
1671   }
1672
1673   // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1674   /* general case */
1675   if (size>1) {
1676     instr=MOVW;
1677   } else {
1678     instr=MOVB;
1679   }
1680   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1681
1682   if (size > 2) {
1683     if (size==3) {
1684       // generic pointer
1685       instr=MOVB;
1686     }
1687     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1688     return;
1689   }
1690 }
1691
1692 /*-----------------------------------------------------------------*/
1693 /* genJumpTab - genrates code for jump table                       */
1694 /*-----------------------------------------------------------------*/
1695 static void genJumpTab (iCode * ic) {
1696   printIc (0, "genJumpTab", ic, 0,0,0);
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* genCast - gen code for casting                                  */
1701 /*-----------------------------------------------------------------*/
1702 static void genCast (iCode * ic) {
1703   int size;
1704   operand *result=IC_RESULT(ic);
1705   operand *right=IC_RIGHT(ic);
1706   sym_link *ctype=operandType(IC_LEFT(ic));
1707   sym_link *rtype=operandType(IC_RIGHT(ic));
1708   sym_link *etype=getSpec(rtype);
1709   short ptrType, signedness;
1710
1711   printIc (0, "genCast", ic, 1,1,1);
1712
1713   aopOp(result, TRUE, TRUE);
1714   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1715   size=AOP_SIZE(result);
1716   
1717   /* if result is a bit */
1718   if (AOP_TYPE(result) == AOP_BIT) {
1719     /* if right is literal, we know what the value is */
1720     if (AOP_TYPE(right) == AOP_LIT) {
1721       if (operandLitValue(right)) {
1722         emitcode ("setb", AOP_NAME(result)[0]);
1723       } else {
1724         emitcode ("clr", AOP_NAME(result)[0]);
1725       }
1726       return;
1727     }
1728     /* if right is also a bit */
1729     if (AOP_TYPE(right) == AOP_BIT) {
1730       emitcode ("mov", "c,%s", AOP_NAME(right));
1731       emitcode ("mov", "%s,c", AOP_NAME(result));
1732       return;
1733     }
1734     /* we need to or */
1735     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1736     return;
1737   }
1738
1739   /* if right is a bit */
1740   if (AOP_TYPE(right)==AOP_BIT) {
1741     emitcode ("mov", "c,%s", AOP_NAME(right));
1742     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1743     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1744     if (size>2) {
1745       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1746     }
1747     return;
1748   }
1749
1750   /* if the result is of type pointer */
1751   if (IS_PTR (ctype)) {
1752
1753     if (AOP_SIZE(right)>1) {
1754       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1755     } else {
1756       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1757       emitcode ("sext", "r1h");
1758       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1759     }
1760     
1761     /* if pointer to generic pointer */
1762     if (IS_GENPTR (ctype)) {
1763             
1764       if (IS_GENPTR (rtype)) {
1765         bailOut("genCast: gptr -> gptr");
1766       }
1767
1768       if (IS_PTR (rtype)) {
1769         ptrType = DCL_TYPE (rtype);
1770       } else {
1771         /* we have to go by the storage class */
1772         if (!SPEC_OCLS(etype)) {
1773           ptrType=0; // hush the compiler
1774           bailOut("genCast: unknown storage class");
1775         } else {
1776           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1777         }
1778       }
1779       
1780       /* the generic part depends on the type */
1781       switch (ptrType)
1782         {
1783         case POINTER:
1784           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1785           break;
1786         case FPOINTER:
1787           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1788           break;
1789         case CPOINTER:
1790           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1791           break;
1792         default:
1793           bailOut("genCast: got unknown storage class");
1794         }
1795     }
1796     return;
1797   }
1798
1799   /* do we have to sign extend? */
1800   signedness = SPEC_USIGN(rtype);
1801
1802   /* now depending on the size */
1803   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1804     {
1805     case 0x44:
1806     case 0x33:
1807       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1808       // fall through
1809     case 0x24:
1810     case 0x22:
1811     case 0x11:
1812       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1813       return;
1814     case 0x42:
1815       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1816       if (signedness) {
1817         emitcode("sext", "%s", AOP_NAME(result)[1]);
1818       } else {
1819         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1820       }
1821       return;
1822     case 0x41:
1823     case 0x21:
1824       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1825       if (signedness) {
1826         emitcode("sext", "r1h");
1827       } else {
1828         emitcode("mov", "r1h,#0");
1829       }
1830       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1831       if (size==2)
1832         return;
1833       // fall through: case 0x41
1834       if (signedness) {
1835         emitcode("sext", "r1");
1836       } else {
1837         emitcode("mov", "r1,#0");
1838       }
1839       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1840       return;
1841     case 0x14:
1842     case 0x12:
1843       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1844       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1845       return;
1846     }
1847   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1848           AOP_SIZE(result), AOP_SIZE(right));
1849   bailOut("genCast: unknown size");
1850 }
1851
1852
1853 /*-----------------------------------------------------------------*/
1854 /* genDjnz - generate decrement & jump if not zero instrucion      */
1855 /*-----------------------------------------------------------------*/
1856 static bool genDjnz (iCode * ic, iCode * ifx) {
1857   symbol *lbl, *lbl1;
1858
1859   if (!ifx)
1860     return 0;
1861
1862   /* if the if condition has a false label
1863      then we cannot save */
1864   if (IC_FALSE (ifx))
1865     return 0;
1866
1867   /* if the minus is not of the form
1868      a = a - 1 */
1869   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1870       !IS_OP_LITERAL (IC_RIGHT (ic)))
1871     return 0;
1872
1873   if (operandLitValue (IC_RIGHT (ic)) != 1)
1874     return 0;
1875
1876   /* if the size of this greater than two then no
1877      saving */
1878   if (getSize (operandType (IC_RESULT (ic))) > 2)
1879     return 0;
1880
1881   printIc (0, "genDjnz", ic, 1,1,1);
1882
1883   /* otherwise we can save BIG */
1884   lbl = newiTempLabel (NULL);
1885   lbl1 = newiTempLabel (NULL);
1886
1887   aopOp (IC_RESULT (ic), FALSE, TRUE);
1888
1889   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1890     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1891     emitcode ("br", "%05d$", lbl1->key + 100);
1892     emitcode ("", "%05d$:", lbl->key + 100);
1893     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1894     emitcode ("", "%05d$:", lbl1->key + 100);
1895     return TRUE;
1896   }
1897
1898   bailOut("genDjnz: aop type");
1899   return FALSE;
1900 }
1901
1902 /*-----------------------------------------------------------------*/
1903 /* genReceive - generate code for a receive iCode                  */
1904 /*-----------------------------------------------------------------*/
1905 static void genReceive (iCode * ic) {
1906   printIc (0, "genReceive", ic, 1,0,0);
1907 }
1908
1909 /*-----------------------------------------------------------------*/
1910 /* gen51Code - generate code for 8051 based controllers            */
1911 /*-----------------------------------------------------------------*/
1912 void genXA51Code (iCode * lic) {
1913   iCode *ic;
1914   int cln = 0;
1915   
1916   lineHead = lineCurr = NULL;
1917   
1918   /* if debug information required */
1919   if (options.debug && currFunc)
1920     {
1921       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1922       _G.debugLine = 1;
1923       if (IS_STATIC (currFunc->etype))
1924         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1925       else
1926         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1927       _G.debugLine = 0;
1928     }
1929   
1930   for (ic = lic; ic; ic = ic->next) {
1931     if (ic->lineno && cln != ic->lineno) {
1932       if (options.debug) {
1933         _G.debugLine = 1;
1934         emitcode ("", "C$%s$%d$%d$%d ==.",
1935                   FileBaseName (ic->filename), ic->lineno,
1936                   ic->level, ic->block);
1937         _G.debugLine = 0;
1938       }
1939       if (!options.noCcodeInAsm) {
1940         emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1941                   printCLine(ic->filename, ic->lineno));
1942       }
1943       cln = ic->lineno;
1944     }
1945     if (options.iCodeInAsm) {
1946       emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1947     }
1948     
1949     /* if the result is marked as
1950        spilt and rematerializable or code for
1951        this has already been generated then
1952        do nothing */
1953     if (resultRemat (ic) || ic->generated)
1954       continue;
1955     
1956     /* depending on the operation */
1957     switch (ic->op)
1958       {
1959       case '!':
1960         genNot (ic);
1961         break;
1962         
1963       case '~':
1964         genCpl (ic);
1965         break;
1966         
1967       case UNARYMINUS:
1968         genUminus (ic);
1969         break;
1970         
1971       case IPUSH:
1972         genIpush (ic);
1973         break;
1974         
1975       case IPOP:
1976         /* IPOP happens only when trying to restore a
1977            spilt live range, if there is an ifx statement
1978            following this pop then the if statement might
1979            be using some of the registers being popped which
1980            would destory the contents of the register so
1981            we need to check for this condition and handle it */
1982         if (ic->next &&
1983             ic->next->op == IFX &&
1984             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1985           genIfx (ic->next, ic);
1986         else
1987           genIpop (ic);
1988         break;
1989         
1990       case CALL:
1991         genCall (ic);
1992         break;
1993         
1994       case PCALL:
1995         genPcall (ic);
1996         break;
1997         
1998       case FUNCTION:
1999         genFunction (ic);
2000         break;
2001         
2002       case ENDFUNCTION:
2003         genEndFunction (ic);
2004         break;
2005         
2006       case RETURN:
2007         genRet (ic);
2008         break;
2009         
2010       case LABEL:
2011         genLabel (ic);
2012         break;
2013         
2014       case GOTO:
2015         genGoto (ic);
2016         break;
2017         
2018       case '+':
2019         genPlus (ic);
2020         break;
2021         
2022       case '-':
2023         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2024           genMinus (ic);
2025         break;
2026         
2027       case '*':
2028         genMult (ic);
2029         break;
2030         
2031       case '/':
2032         genDiv (ic);
2033         break;
2034         
2035       case '%':
2036         genMod (ic);
2037         break;
2038         
2039       case '>':
2040         genCmpGt (ic);
2041         break;
2042         
2043       case '<':
2044         genCmpLt (ic);
2045         break;
2046         
2047       case LE_OP:
2048       case GE_OP:
2049       case NE_OP:
2050
2051         /* note these two are xlated by algebraic equivalence
2052            during parsing SDCC.y */
2053         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2054                 "got '>=' or '<=' shouldn't have come here");
2055         break;
2056
2057       case EQ_OP:
2058         genCmpEq (ic);
2059         break;
2060         
2061       case AND_OP:
2062         genAndOp (ic);
2063         break;
2064         
2065       case OR_OP:
2066         genOrOp (ic);
2067         break;
2068         
2069       case '^':
2070         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2071         break;
2072         
2073       case '|':
2074         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2075         break;
2076         
2077       case BITWISEAND:
2078         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2079         break;
2080         
2081       case INLINEASM:
2082         genInline (ic);
2083         break;
2084         
2085       case RRC:
2086         genRRC (ic);
2087         break;
2088         
2089       case RLC:
2090         genRLC (ic);
2091         break;
2092         
2093       case GETHBIT:
2094         genGetHbit (ic);
2095         break;
2096         
2097       case LEFT_OP:
2098         genLeftShift (ic);
2099         break;
2100         
2101       case RIGHT_OP:
2102         genRightShift (ic);
2103         break;
2104         
2105       case GET_VALUE_AT_ADDRESS:
2106         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2107         break;
2108         
2109       case '=':
2110         if (POINTER_SET (ic))
2111           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2112         else
2113           genAssign (ic);
2114         break;
2115         
2116       case IFX:
2117         genIfx (ic, NULL);
2118         break;
2119         
2120       case ADDRESS_OF:
2121         genAddrOf (ic);
2122         break;
2123         
2124       case JUMPTABLE:
2125         genJumpTab (ic);
2126         break;
2127         
2128       case CAST:
2129         genCast (ic);
2130         break;
2131         
2132       case RECEIVE:
2133         genReceive (ic);
2134         break;
2135         
2136       case SEND:
2137         addSet (&_G.sendSet, ic);
2138         break;
2139         
2140       default:
2141         ic = ic;
2142       }
2143   }
2144   
2145   
2146   /* now we are ready to call the
2147      peep hole optimizer */
2148   if (!options.nopeep)
2149     peepHole (&lineHead);
2150   
2151   /* now do the actual printing */
2152   printLine (lineHead, codeOutFile);
2153   return;
2154 }