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