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