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