aa05c37e10aa3c28815f4f2fa508f09fc24bd5c1
[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 (char *op, iCode * ic, bool result, bool left, bool right) {
587   char line[132];
588
589   sprintf (line, "%s(%d)", op, ic->lineno);
590   if (result) {
591     strcat (line, " result=");
592     strcat (line, printOp (IC_RESULT(ic)));
593   }
594   if (left) {
595     strcat (line, " left=");
596     strcat (line, printOp (IC_LEFT(ic)));
597   }
598   if (right) {
599     strcat (line, " right=");
600     strcat (line, printOp (IC_RIGHT(ic)));
601   }
602   emitcode (";", line);
603 }
604
605 /*-----------------------------------------------------------------*/
606 /* toBoolean - return carry for operand!=0                           */
607 /*-----------------------------------------------------------------*/
608 static char *toBoolean (operand * op) {
609   symbol *tlbl=newiTempLabel(NULL);
610
611   switch (AOP_SIZE(op)) 
612     {
613     case 1:
614     case 2:
615       emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
616                 "This needs a second thought");
617       
618       emitcode ("", "%05d$:", tlbl->key+100);
619       return "c";
620     }
621
622   bailOut("toBoolean: unknown size");
623   return NULL;
624 }
625
626 /*-----------------------------------------------------------------*/
627 /* regsInCommon - two operands have some registers in common       */
628 /*-----------------------------------------------------------------*/
629 static bool regsInCommon (operand * op1, operand * op2) {
630   symbol *sym1, *sym2;
631   int i;
632
633   /* if they have registers in common */
634   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
635     return FALSE;
636
637   sym1 = OP_SYMBOL (op1);
638   sym2 = OP_SYMBOL (op2);
639
640   if (sym1->nRegs == 0 || sym2->nRegs == 0)
641     return FALSE;
642
643   for (i = 0; i < sym1->nRegs; i++)
644     {
645       int j;
646       if (!sym1->regs[i])
647         continue;
648
649       for (j = 0; j < sym2->nRegs; j++)
650         {
651           if (!sym2->regs[j])
652             continue;
653
654           if (sym2->regs[j] == sym1->regs[i])
655             return TRUE;
656         }
657     }
658
659   return FALSE;
660 }
661
662 /*-----------------------------------------------------------------*/
663 /* resultRemat - result  is rematerializable                       */
664 /*-----------------------------------------------------------------*/
665 static int resultRemat (iCode * ic) {
666   if (SKIP_IC (ic) || ic->op == IFX)
667     return 0;
668   
669   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
670     {
671       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
672       if (sym->remat && !POINTER_SET (ic))
673         return 1;
674     }
675   
676   return 0;
677 }
678
679 /*-----------------------------------------------------------------*/
680 /* genNot - generate code for ! operation                          */
681 /*-----------------------------------------------------------------*/
682 static void genNot (iCode * ic) {
683   printIc("genNot:", ic, 1,1,0);
684 }
685
686 /*-----------------------------------------------------------------*/
687 /* genCpl - generate code for complement                           */
688 /*-----------------------------------------------------------------*/
689 static void genCpl (iCode * ic) {
690   printIc("genCpl", ic, 1,1,0);
691 }
692
693 /*-----------------------------------------------------------------*/
694 /* genUminus - unary minus code generation                         */
695 /*-----------------------------------------------------------------*/
696 static void genUminus (iCode * ic) {
697   printIc("genUminus", ic, 1,1,0);
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* genIpush - generate code for pushing                            */
702 /*-----------------------------------------------------------------*/
703 static void genIpush (iCode * ic) {
704   operand *left=IC_LEFT(ic);
705
706   printIc ("genIpush", ic, 0,1,0);
707   aopOp(left,FALSE,FALSE);
708
709
710   if (AOP_TYPE(left)==AOP_LIT) {
711     switch (AOP_SIZE(left)) 
712       {
713       case 1:
714         emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
715         emitcode ("push", "r1l");
716         _G.parmsPushed++;
717         return;
718       case 2:
719         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
720         emitcode ("push", "r1");
721         _G.parmsPushed++;
722         return;
723       case 3:
724         emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
725         emitcode ("push", "r1l");
726         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
727         emitcode ("push", "r1");
728         _G.parmsPushed += 2;
729         return;
730       case 4:
731         emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
732         emitcode ("push", "r1");
733         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
734         emitcode ("push", "r1");
735         _G.parmsPushed += 2;
736         return;
737       }
738   } else {
739     if (AOP_SIZE(left)>2) {
740       emitcode ("push", "%s", AOP_NAME(left)[1]);
741       _G.parmsPushed++;
742     }
743     emitcode ("push", "%s", AOP_NAME(left)[0]);
744     _G.parmsPushed++;
745   }
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* genIpop - recover the registers: can happen only for spilling   */
750 /*-----------------------------------------------------------------*/
751 static void genIpop (iCode * ic) {
752   printIc ("genIpop", ic, 0,1,0);
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* genCall - generates a call statement                            */
757 /*-----------------------------------------------------------------*/
758 static void genCall (iCode * ic) {
759   operand *result=IC_RESULT(ic);
760
761   emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
762             OP_SYMBOL(IC_LEFT(ic))->name,
763             printOp (IC_RESULT(ic)));
764   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
765
766   /* readjust the stack if we have pushed some parms */
767   if (_G.parmsPushed) {
768     emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
769     _G.parmsPushed=0;
770   }
771
772   /* if we need to assign a result value */
773   if (IS_ITEMP (IC_RESULT(ic)) &&
774       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
775     aopOp(result,FALSE,FALSE);
776     switch (AOP_SIZE(result))
777       {
778       case 1:
779         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
780         return;
781       case 2:
782         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
783         return;
784       case 3:
785         // generic pointer
786         emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
787         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
788         return;
789       case 4:
790         emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
791         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
792         return;
793       }
794     bailOut("genCall");
795   }
796 }
797
798 /*-----------------------------------------------------------------*/
799 /* genPcall - generates a call by pointer statement                */
800 /*-----------------------------------------------------------------*/
801 static void
802 genPcall (iCode * ic)
803 {
804   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* genFunction - generated code for function entry                 */
809 /*-----------------------------------------------------------------*/
810 static void genFunction (iCode * ic) {
811   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
812   sym_link *type=sym->type;
813
814   emitcode (";", "genFunction %s", sym->rname);
815
816   /* print the allocation information */
817   printAllocInfo (currFunc, codeOutFile);
818
819   emitcode ("", "%s:", sym->rname);
820
821   if (IFFUNC_ISNAKED(type))
822   {
823       emitcode(";", "naked function: no prologue.");
824       return;
825   }
826
827   /* adjust the stack for locals used in this function */
828   if (sym->stack) {
829     emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
830   }
831 }
832
833 /*-----------------------------------------------------------------*/
834 /* genEndFunction - generates epilogue for functions               */
835 /*-----------------------------------------------------------------*/
836 static void
837 genEndFunction (iCode * ic)
838 {
839   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
840
841   printIc ("genEndFunction", ic, 0,0,0);
842
843   if (IFFUNC_ISNAKED(sym->type)) {
844       emitcode(";", "naked function: no epilogue.");
845       return;
846   }
847
848   /* readjust the stock for locals used in this function */
849   if (sym->stack) {
850     emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
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 ("genRet", ic, 0, 0, 0);
867   } else {
868     printIc ("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 ("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 (whatever)* = (whatever)** + 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   printIc ("genMinus", ic, 1,1,1);
996 }
997
998
999 /*-----------------------------------------------------------------*/
1000 /* genMult - generates code for multiplication                     */
1001 /*-----------------------------------------------------------------*/
1002 static void genMult (iCode * ic) {
1003   printIc ("genMult", ic, 1,1,1);
1004 }
1005
1006 /*-----------------------------------------------------------------*/
1007 /* genDiv - generates code for division                            */
1008 /*-----------------------------------------------------------------*/
1009 static void genDiv (iCode * ic) {
1010   printIc ("genDiv", ic, 1,1,1);
1011 }
1012
1013 /*-----------------------------------------------------------------*/
1014 /* genMod - generates code for division                            */
1015 /*-----------------------------------------------------------------*/
1016 static void genMod (iCode * ic) {
1017   printIc ("genMod", ic, 1,1,1);
1018 }
1019
1020  /*-----------------------------------------------------------------*/
1021 /* genCmpGt :- greater than comparison                             */
1022 /*-----------------------------------------------------------------*/
1023 static void genCmpGt (iCode * ic) {
1024   printIc ("genCmpGt", ic, 1,1,1);
1025 }
1026 /*-----------------------------------------------------------------*/
1027 /* genCmpLt - less than comparisons                                */
1028 /*-----------------------------------------------------------------*/
1029 static void genCmpLt (iCode * ic) {
1030   printIc ("genCmpLt", ic, 1,1,1);
1031 }
1032 /*-----------------------------------------------------------------*/
1033 /* genCmpEq - generates code for equal to                          */
1034 /*-----------------------------------------------------------------*/
1035 static void genCmpEq (iCode * ic) {
1036   printIc ("genCmpEq", ic, 1,1,1);
1037 }
1038
1039 /*-----------------------------------------------------------------*/
1040 /* ifxForOp - returns the icode containing the ifx for operand     */
1041 /*-----------------------------------------------------------------*/
1042 static iCode *ifxForOp (operand * op, iCode * ic) {
1043   /* if true symbol then needs to be assigned */
1044   if (IS_TRUE_SYMOP (op))
1045     return NULL;
1046   
1047   /* if this has register type condition and
1048      the next instruction is ifx with the same operand
1049      and live to of the operand is upto the ifx only then */
1050   if (ic->next &&
1051       ic->next->op == IFX &&
1052       IC_COND (ic->next)->key == op->key &&
1053       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1054     return ic->next;
1055   
1056   return NULL;
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* hasInc - operand is incremented before any other use            */
1061 /*-----------------------------------------------------------------*/
1062 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1063   sym_link *type = operandType(op);
1064   sym_link *retype = getSpec (type);
1065   iCode *lic = ic->next;
1066   int isize ;
1067   
1068   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1069   if (!IS_SYMOP(op)) return NULL;
1070
1071   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1072   if (IS_AGGREGATE(type->next)) return NULL;
1073   if (osize != (isize = getSize(type->next))) return NULL;
1074
1075   while (lic) {
1076     /* if operand of the form op = op + <sizeof *op> */
1077     if (lic->op == '+') {
1078       if (isOperandEqual(IC_LEFT(lic),op) &&
1079           //isOperandEqual(IC_RESULT(lic),op) && 
1080           isOperandLiteral(IC_RIGHT(lic)) &&
1081           operandLitValue(IC_RIGHT(lic)) == isize) {
1082         emitcode (";", "Found hasInc");
1083         return lic;
1084       }
1085     }
1086     /* if the operand used or deffed */
1087     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1088       return NULL;
1089     }
1090     /* if GOTO or IFX */
1091     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1092     lic = lic->next;
1093   }
1094   return NULL;
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* genAndOp - for && operation                                     */
1099 /*-----------------------------------------------------------------*/
1100 static void genAndOp (iCode * ic) {
1101   printIc ("genAndOp(&&)", ic, 1,1,1);
1102 }
1103
1104 /*-----------------------------------------------------------------*/
1105 /* genOrOp - for || operation                                      */
1106 /*-----------------------------------------------------------------*/
1107 static void genOrOp (iCode * ic) {
1108   printIc ("genOrOp(||)", ic, 1,1,1);
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genAnd  - code for and                                            */
1113 /*-----------------------------------------------------------------*/
1114 static void genAnd (iCode * ic, iCode * ifx) {
1115   printIc ("genAnd", ic, 1,1,1);
1116 }
1117
1118 /*-----------------------------------------------------------------*/
1119 /* genOr  - code for or                                            */
1120 /*-----------------------------------------------------------------*/
1121 static void genOr (iCode * ic, iCode * ifx) {
1122   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1123   int size;
1124   char *instr;
1125
1126   printIc ("genOr", ic, 1,1,1);
1127
1128   size=aopOp(result, TRUE, TRUE);
1129
1130   /* if left is a literal, then exchange them */
1131   if (IS_LITERAL(operandType(left))) {
1132     operand *tmp = right;
1133     right = left;
1134     left = tmp;
1135   }
1136     
1137   if (aopIsBit(result)) {
1138     if (IS_LITERAL(operandType(right))) {
1139       if (operandLitValue(right)) {
1140         emitcode ("setb", AOP_NAME(result)[0]);
1141         return;
1142       }
1143       aopOp(left, TRUE, TRUE);
1144       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1145       return;
1146     }
1147   }
1148   
1149   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1150   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1151
1152   if (size>1) {
1153     instr="or.w";
1154   } else {
1155     instr="or.b";
1156   }
1157   if (!aopEqual(result->aop, left->aop, 0)) {
1158     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1159   }
1160   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1161   if (size>2) {
1162     if (!aopEqual(result->aop, left->aop, 1)) {
1163       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1164     }
1165     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1166   }
1167   return;
1168 }
1169
1170 /*-----------------------------------------------------------------*/
1171 /* genXor - code for xclusive or                                   */
1172 /*-----------------------------------------------------------------*/
1173 static void genXor (iCode * ic, iCode * ifx) {
1174   printIc ("genXor", ic, 1,1,1);
1175 }
1176
1177 /*-----------------------------------------------------------------*/
1178 /* genInline - write the inline code out                           */
1179 /*-----------------------------------------------------------------*/
1180 static void genInline (iCode * ic) {
1181
1182   printIc ("genInline", ic, 0,0,0);
1183   
1184   emitcode ("", IC_INLINE(ic));
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* genRRC - rotate right with carry                                */
1189 /*-----------------------------------------------------------------*/
1190 static void genRRC (iCode * ic) {
1191   printIc ("genRRC", ic, 1,1,0);
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* genRLC - generate code for rotate left with carry               */
1196 /*-----------------------------------------------------------------*/
1197 static void genRLC (iCode * ic) {
1198   printIc ("genRLC", ic, 1,1,0);
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* genGetHbit - generates code get highest order bit               */
1203 /*-----------------------------------------------------------------*/
1204 static void genGetHbit (iCode * ic) {
1205   printIc ("genGetHbit", ic, 1,1,0);
1206 }
1207
1208 /*-----------------------------------------------------------------*/
1209 /* genLeftShift - generates code for left shifting                 */
1210 /*-----------------------------------------------------------------*/
1211 static void genLeftShift (iCode * ic) {
1212   printIc ("genLeftShift", ic, 1,1,1);
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* genRightShift - generate code for right shifting                */
1217 /*-----------------------------------------------------------------*/
1218 static void genRightShift (iCode * ic) {
1219   printIc ("genRightShift", ic, 1,1,1);
1220 }
1221
1222 /*-----------------------------------------------------------------*/
1223 /* genPointerGet - generate code for pointer get                   */
1224 /*-----------------------------------------------------------------*/
1225 static void genPointerGet (iCode * ic, iCode *pi) {
1226   char *instr, *scratchReg;
1227   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1228   bool codePointer=IS_CODEPTR(operandType(left));
1229   int size;
1230
1231   if (pi) {
1232     printIc ("genPointerGet pi", ic, 1,1,0);
1233   } else {
1234     printIc ("genPointerGet", ic, 1,1,0);
1235   }
1236
1237   if (!IS_PTR(operandType(left))) {
1238     bailOut ("genPointerGet: pointer required");
1239   }
1240
1241   aopOp(left,FALSE,FALSE);
1242   size=aopOp(result,TRUE,aopIsDir(left));
1243
1244   if (IS_GENPTR(operandType(left))) {
1245     symbol *tlbl1=newiTempLabel(NULL);
1246     symbol *tlbl2=newiTempLabel(NULL);
1247     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1248     emitcode ("beq", "%05d$", tlbl1->key+100);
1249     // far/near pointer
1250     if (pi) {
1251       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1252       pi->generated=1;
1253     } else {
1254       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1255     }
1256     if (size>2) {
1257       if (pi) {
1258         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1259       } else {
1260         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1261       }
1262     }
1263     emitcode ("br", "%05d$", tlbl2->key+100);
1264     emitcode ("", "%05d$:", tlbl1->key+100);
1265     // code pointer
1266     if (pi) {
1267       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1268       pi->generated=1;
1269     } else {
1270       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1271       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1272     }
1273     if (size>2) {
1274       if (pi) {
1275         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1276       } else {
1277         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1278       }
1279     }
1280     emitcode ("", "%05d$:", tlbl2->key+100);
1281     return;
1282   }
1283
1284   switch (AOP_TYPE(left)) 
1285     {
1286     case AOP_LIT:
1287       emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1288       sprintf (AOP_NAME(left)[0], "r1");
1289       // fall through
1290     case AOP_REG:
1291       if (size>1) {
1292         if (codePointer) {
1293           instr=MOVCW;
1294         } else {
1295           instr=MOVW;
1296         }
1297         scratchReg=R1;
1298       } else {
1299         if (codePointer) {
1300           instr=MOVCB;
1301         } else {
1302           instr=MOVB;
1303         }
1304         scratchReg=R1L;
1305       }
1306       if (AOP_TYPE(result)==AOP_STK) {
1307         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1308         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1309       } else {
1310         if (pi) {
1311           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1312                     AOP_NAME(left)[0]);
1313           pi->generated=1;
1314         } else {
1315           if (codePointer) {
1316             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1317             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1318           } else {
1319             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1320                       AOP_NAME(left)[0]);
1321           }
1322         }
1323       }
1324       if (size > 2) {
1325         if (size==3) {
1326           if (codePointer) {
1327             instr=MOVCB;
1328           } else {
1329             instr=MOVB;
1330           }
1331           scratchReg=R1L;
1332         }
1333         if (AOP_TYPE(result)==AOP_STK) {
1334           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1335           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1336         } else {
1337           if (pi) {
1338             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1339                       AOP_NAME(left)[0]);
1340           } else {
1341             if (codePointer) {
1342               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1343             } else {
1344               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1345                         AOP_NAME(left)[0]);
1346             }
1347           }
1348         }
1349       }
1350       return;
1351     }
1352   bailOut ("genPointerGet");
1353 }
1354
1355 /*-----------------------------------------------------------------*/
1356 /* genPointerSet - stores the value into a pointer location        */
1357 /*-----------------------------------------------------------------*/
1358 static void genPointerSet (iCode * ic, iCode *pi) {
1359   char *instr;
1360   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1361   int size;
1362
1363   printIc ("genPointerSet", ic, 1,0,1);
1364
1365   if (!IS_PTR(operandType(result))) {
1366     bailOut ("genPointerSet: pointer required");
1367   }
1368
1369   aopOp(result,FALSE,FALSE);
1370   size=aopOp(right,FALSE, FALSE);
1371
1372   if (IS_GENPTR(operandType(result))) {
1373     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1374               AOP_NAME(result)[0], AOP_NAME(result)[1],
1375               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1376     return;
1377   }
1378
1379   switch (AOP_TYPE(right)) 
1380     {
1381     case AOP_LIT:
1382     case AOP_REG:
1383       if (size>1) {
1384         instr=MOVW;
1385       } else {
1386         instr=MOVB;
1387       }
1388       if (pi) {
1389         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1390         pi->generated=1;
1391       } else {
1392         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1393       }
1394       if (size > 2) {
1395         if (size==3) {
1396           instr=MOVB;
1397         }
1398         if (pi) {
1399           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1400                     AOP_NAME(right)[1]);
1401         } else {
1402           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1403                     AOP_NAME(right)[1]);
1404         }
1405       }
1406       return;
1407     }
1408   bailOut ("genPointerSet");
1409 }
1410
1411 /*-----------------------------------------------------------------*/
1412 /* genIfx - generate code for Ifx statement                        */
1413 /*-----------------------------------------------------------------*/
1414 static void genIfx (iCode * ic, iCode * popIc) {
1415   int size;
1416   char *instr;
1417   bool trueOrFalse;
1418   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1419   operand *cond=IC_COND(ic);
1420
1421   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1422             ic->lineno, printOp(cond),
1423             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1424             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1425
1426   size=aopOp(cond,TRUE,TRUE);
1427
1428   if (IC_TRUE(ic)) {
1429     trueOrFalse=TRUE;
1430     jlbl=IC_TRUE(ic);
1431   } else {
1432     trueOrFalse=FALSE;
1433     jlbl=IC_FALSE(ic);
1434   }
1435
1436   switch (AOP_TYPE(cond) )
1437     {
1438     case AOP_BIT:
1439       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1440                 AOP_NAME(cond)[0], tlbl->key+100);
1441       emitcode ("jmp", "%05d$", jlbl->key+100);
1442       emitcode ("", "%05d$:", tlbl->key+100);
1443       return;
1444     case AOP_REG:
1445     case AOP_DIR:
1446     case AOP_FAR:
1447     case AOP_STK:
1448       if (size>1) {
1449         instr="cmp.w";
1450       } else {
1451         instr="cmp.b";
1452       }
1453       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1454       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1455       if (size > 2) {
1456         if (size==3) {
1457           // generic pointer, forget the generic part
1458         } else {
1459           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1460           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1461         }
1462       }
1463       emitcode ("jmp", "%05d$", jlbl->key+100);
1464       emitcode ("", "%05d$:", tlbl->key+100);
1465       return;
1466     }
1467   bailOut ("genIfx");
1468 }
1469
1470 /*-----------------------------------------------------------------*/
1471 /* genAddrOf - generates code for address of                       */
1472 /*-----------------------------------------------------------------*/
1473 static void genAddrOf (iCode * ic) {
1474   int size;
1475   operand *left=IC_LEFT(ic);
1476
1477   printIc ("genAddrOf", ic, 1,1,0);
1478
1479   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1480
1481   if (isOperandOnStack(left)) {
1482     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1483               getStackOffset(OP_SYMBOL(left)->stack));
1484     if (size > 2) {
1485       // this must be a generic pointer
1486       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1487     }
1488     return;
1489   }
1490
1491   if (isOperandInDirSpace(left) ||
1492       isOperandInFarSpace(left) ||
1493       isOperandInCodeSpace(left)) {
1494     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1495               OP_SYMBOL(left)->rname);
1496     if (size > 2) {
1497       // this must be a generic pointer
1498       int space=0; // dir space
1499       if (isOperandInFarSpace(left)) {
1500         space=1;
1501       } else if (isOperandInCodeSpace(left)) {
1502         space=2;
1503       }
1504       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1505     }
1506     return;
1507   }
1508
1509   bailOut("genAddrOf");
1510 }
1511
1512 /*-----------------------------------------------------------------*/
1513 /* genAssign - generate code for assignment                        */
1514 /*-----------------------------------------------------------------*/
1515 static void genAssign (iCode * ic) {
1516   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1517   int size;
1518   char *instr;
1519
1520   printIc ("genAssign", ic, 1,0,1);
1521   
1522   if (!IS_SYMOP(result)) {
1523     bailOut("genAssign: result is not a symbol");
1524   }
1525   
1526   aopOp(result, TRUE, TRUE);
1527   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1528   size=AOP_SIZE(result);
1529
1530   /* if result is a bit */
1531   if (AOP_TYPE(result) == AOP_BIT) {
1532     /* if right is literal, we know what the value is */
1533     if (AOP_TYPE(right) == AOP_LIT) {
1534       if (operandLitValue(right)) {
1535         emitcode ("setb", AOP_NAME(result)[0]);
1536       } else {
1537         emitcode ("clr", AOP_NAME(result)[0]);
1538       }
1539       return;
1540     }
1541     /* if right is also a bit */
1542     if (AOP_TYPE(right) == AOP_BIT) {
1543       emitcode ("mov", "c,%s", AOP_NAME(right));
1544       emitcode ("mov", "%s,c", AOP_NAME(result));
1545       return;
1546     }
1547     /* we need to or */
1548     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1549     return;
1550   }
1551
1552   // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1553   /* general case */
1554   if (size>1) {
1555     instr=MOVW;
1556   } else {
1557     instr=MOVB;
1558   }
1559   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1560
1561   if (size > 2) {
1562     if (size==3) {
1563       // generic pointer
1564       instr=MOVB;
1565     }
1566     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1567     return;
1568   }
1569 }
1570
1571 /*-----------------------------------------------------------------*/
1572 /* genJumpTab - genrates code for jump table                       */
1573 /*-----------------------------------------------------------------*/
1574 static void genJumpTab (iCode * ic) {
1575   printIc ("genJumpTab", ic, 0,0,0);
1576 }
1577
1578 /*-----------------------------------------------------------------*/
1579 /* genCast - gen code for casting                                  */
1580 /*-----------------------------------------------------------------*/
1581 static void genCast (iCode * ic) {
1582   int size;
1583   operand *result=IC_RESULT(ic);
1584   operand *right=IC_RIGHT(ic);
1585   sym_link *ctype=operandType(IC_LEFT(ic));
1586   sym_link *rtype=operandType(IC_RIGHT(ic));
1587   sym_link *etype=getSpec(rtype);
1588   short ptrType, signedness;
1589
1590   printIc ("genCast", ic, 1,1,1);
1591
1592   aopOp(result, TRUE, TRUE);
1593   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1594   size=AOP_SIZE(result);
1595   
1596   /* if result is a bit */
1597   if (AOP_TYPE(result) == AOP_BIT) {
1598     /* if right is literal, we know what the value is */
1599     if (AOP_TYPE(right) == AOP_LIT) {
1600       if (operandLitValue(right)) {
1601         emitcode ("setb", AOP_NAME(result)[0]);
1602       } else {
1603         emitcode ("clr", AOP_NAME(result)[0]);
1604       }
1605       return;
1606     }
1607     /* if right is also a bit */
1608     if (AOP_TYPE(right) == AOP_BIT) {
1609       emitcode ("mov", "c,%s", AOP_NAME(right));
1610       emitcode ("mov", "%s,c", AOP_NAME(result));
1611       return;
1612     }
1613     /* we need to or */
1614     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1615     return;
1616   }
1617
1618   /* if right is a bit */
1619   if (AOP_TYPE(right)==AOP_BIT) {
1620     emitcode ("mov", "c,%s", AOP_NAME(right));
1621     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1622     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1623     if (size>2) {
1624       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1625     }
1626     return;
1627   }
1628
1629   /* if the result is of type pointer */
1630   if (IS_PTR (ctype)) {
1631
1632     if (AOP_SIZE(right)>1) {
1633       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1634     } else {
1635       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1636       emitcode ("sext", "r1h");
1637       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1638     }
1639     
1640     /* if pointer to generic pointer */
1641     if (IS_GENPTR (ctype)) {
1642             
1643       if (IS_GENPTR (rtype)) {
1644         bailOut("genCast: gptr -> gptr");
1645       }
1646
1647       if (IS_PTR (rtype)) {
1648         ptrType = DCL_TYPE (rtype);
1649       } else {
1650         /* we have to go by the storage class */
1651         if (!SPEC_OCLS(etype)) {
1652           ptrType=0; // hush the compiler
1653           bailOut("genCast: unknown storage class");
1654         } else {
1655           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1656         }
1657       }
1658       
1659       /* the generic part depends on the type */
1660       switch (ptrType)
1661         {
1662         case POINTER:
1663           emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1664           break;
1665         case FPOINTER:
1666           emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1667           break;
1668         case CPOINTER:
1669           emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1670           break;
1671         default:
1672           bailOut("genCast: got unknown storage class");
1673         }
1674     }
1675     return;
1676   }
1677
1678   /* do we have to sign extend? */
1679   signedness = SPEC_USIGN(rtype);
1680
1681   /* now depending on the size */
1682   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1683     {
1684     case 0x44:
1685     case 0x33:
1686       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1687       // fall through
1688     case 0x24:
1689     case 0x22:
1690     case 0x11:
1691       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1692       return;
1693     case 0x42:
1694       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1695       if (signedness) {
1696         emitcode("sext", "%s", AOP_NAME(result)[1]);
1697       } else {
1698         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1699       }
1700       return;
1701     case 0x41:
1702     case 0x21:
1703       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1704       if (signedness) {
1705         emitcode("sext", "r1h");
1706       } else {
1707         emitcode("mov", "r1h,#0");
1708       }
1709       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1710       if (size==2)
1711         return;
1712       // fall through: case 0x41
1713       if (signedness) {
1714         emitcode("sext", "r1");
1715       } else {
1716         emitcode("mov", "r1,#0");
1717       }
1718       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1719       return;
1720     case 0x14:
1721     case 0x12:
1722       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1723       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1724       return;
1725     }
1726   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1727           AOP_SIZE(result), AOP_SIZE(right));
1728   bailOut("genCast: unknown size");
1729 }
1730
1731
1732 /*-----------------------------------------------------------------*/
1733 /* genDjnz - generate decrement & jump if not zero instrucion      */
1734 /*-----------------------------------------------------------------*/
1735 static bool genDjnz (iCode * ic, iCode * ifx) {
1736   symbol *lbl, *lbl1;
1737
1738   if (!ifx)
1739     return 0;
1740
1741   /* if the if condition has a false label
1742      then we cannot save */
1743   if (IC_FALSE (ifx))
1744     return 0;
1745
1746   /* if the minus is not of the form
1747      a = a - 1 */
1748   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1749       !IS_OP_LITERAL (IC_RIGHT (ic)))
1750     return 0;
1751
1752   if (operandLitValue (IC_RIGHT (ic)) != 1)
1753     return 0;
1754
1755   /* if the size of this greater than two then no
1756      saving */
1757   if (getSize (operandType (IC_RESULT (ic))) > 2)
1758     return 0;
1759
1760   printIc ("genDjnz", ic, 1,1,1);
1761
1762   /* otherwise we can save BIG */
1763   lbl = newiTempLabel (NULL);
1764   lbl1 = newiTempLabel (NULL);
1765
1766   aopOp (IC_RESULT (ic), FALSE, TRUE);
1767
1768   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1769     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1770     emitcode ("br", "%05d$", lbl1->key + 100);
1771     emitcode ("", "%05d$:", lbl->key + 100);
1772     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1773     emitcode ("", "%05d$:", lbl1->key + 100);
1774     return TRUE;
1775   }
1776
1777   bailOut("genDjnz: aop type");
1778   return FALSE;
1779 }
1780
1781 /*-----------------------------------------------------------------*/
1782 /* genReceive - generate code for a receive iCode                  */
1783 /*-----------------------------------------------------------------*/
1784 static void genReceive (iCode * ic) {
1785   printIc ("genReceive", ic, 1,0,0);
1786 }
1787
1788 /*-----------------------------------------------------------------*/
1789 /* gen51Code - generate code for 8051 based controllers            */
1790 /*-----------------------------------------------------------------*/
1791 void genXA51Code (iCode * lic) {
1792   iCode *ic;
1793   int cln = 0;
1794   
1795   lineHead = lineCurr = NULL;
1796   
1797   /* if debug information required */
1798   if (options.debug && currFunc)
1799     {
1800       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1801       _G.debugLine = 1;
1802       if (IS_STATIC (currFunc->etype))
1803         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1804       else
1805         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1806       _G.debugLine = 0;
1807     }
1808   
1809   for (ic = lic; ic; ic = ic->next) {
1810     if (ic->lineno && cln != ic->lineno) {
1811       if (options.debug) {
1812         _G.debugLine = 1;
1813         emitcode ("", "C$%s$%d$%d$%d ==.",
1814                   FileBaseName (ic->filename), ic->lineno,
1815                   ic->level, ic->block);
1816         _G.debugLine = 0;
1817       }
1818       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1819                 printCLine(ic->filename, ic->lineno));
1820       cln = ic->lineno;
1821     }
1822     /* if the result is marked as
1823        spilt and rematerializable or code for
1824        this has already been generated then
1825        do nothing */
1826     if (resultRemat (ic) || ic->generated)
1827       continue;
1828     
1829     /* depending on the operation */
1830     switch (ic->op)
1831       {
1832       case '!':
1833         genNot (ic);
1834         break;
1835         
1836       case '~':
1837         genCpl (ic);
1838         break;
1839         
1840       case UNARYMINUS:
1841         genUminus (ic);
1842         break;
1843         
1844       case IPUSH:
1845         genIpush (ic);
1846         break;
1847         
1848       case IPOP:
1849         /* IPOP happens only when trying to restore a
1850            spilt live range, if there is an ifx statement
1851            following this pop then the if statement might
1852            be using some of the registers being popped which
1853            would destory the contents of the register so
1854            we need to check for this condition and handle it */
1855         if (ic->next &&
1856             ic->next->op == IFX &&
1857             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1858           genIfx (ic->next, ic);
1859         else
1860           genIpop (ic);
1861         break;
1862         
1863       case CALL:
1864         genCall (ic);
1865         break;
1866         
1867       case PCALL:
1868         genPcall (ic);
1869         break;
1870         
1871       case FUNCTION:
1872         genFunction (ic);
1873         break;
1874         
1875       case ENDFUNCTION:
1876         genEndFunction (ic);
1877         break;
1878         
1879       case RETURN:
1880         genRet (ic);
1881         break;
1882         
1883       case LABEL:
1884         genLabel (ic);
1885         break;
1886         
1887       case GOTO:
1888         genGoto (ic);
1889         break;
1890         
1891       case '+':
1892         genPlus (ic);
1893         break;
1894         
1895       case '-':
1896         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1897           genMinus (ic);
1898         break;
1899         
1900       case '*':
1901         genMult (ic);
1902         break;
1903         
1904       case '/':
1905         genDiv (ic);
1906         break;
1907         
1908       case '%':
1909         genMod (ic);
1910         break;
1911         
1912       case '>':
1913         genCmpGt (ic);
1914         break;
1915         
1916       case '<':
1917         genCmpLt (ic);
1918         break;
1919         
1920       case LE_OP:
1921       case GE_OP:
1922       case NE_OP:
1923
1924         /* note these two are xlated by algebraic equivalence
1925            during parsing SDCC.y */
1926         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1927                 "got '>=' or '<=' shouldn't have come here");
1928         break;
1929
1930       case EQ_OP:
1931         genCmpEq (ic);
1932         break;
1933         
1934       case AND_OP:
1935         genAndOp (ic);
1936         break;
1937         
1938       case OR_OP:
1939         genOrOp (ic);
1940         break;
1941         
1942       case '^':
1943         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1944         break;
1945         
1946       case '|':
1947         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1948         break;
1949         
1950       case BITWISEAND:
1951         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1952         break;
1953         
1954       case INLINEASM:
1955         genInline (ic);
1956         break;
1957         
1958       case RRC:
1959         genRRC (ic);
1960         break;
1961         
1962       case RLC:
1963         genRLC (ic);
1964         break;
1965         
1966       case GETHBIT:
1967         genGetHbit (ic);
1968         break;
1969         
1970       case LEFT_OP:
1971         genLeftShift (ic);
1972         break;
1973         
1974       case RIGHT_OP:
1975         genRightShift (ic);
1976         break;
1977         
1978       case GET_VALUE_AT_ADDRESS:
1979         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1980         break;
1981         
1982       case '=':
1983         if (POINTER_SET (ic))
1984           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1985         else
1986           genAssign (ic);
1987         break;
1988         
1989       case IFX:
1990         genIfx (ic, NULL);
1991         break;
1992         
1993       case ADDRESS_OF:
1994         genAddrOf (ic);
1995         break;
1996         
1997       case JUMPTABLE:
1998         genJumpTab (ic);
1999         break;
2000         
2001       case CAST:
2002         genCast (ic);
2003         break;
2004         
2005       case RECEIVE:
2006         genReceive (ic);
2007         break;
2008         
2009       case SEND:
2010         addSet (&_G.sendSet, ic);
2011         break;
2012         
2013       default:
2014         ic = ic;
2015       }
2016   }
2017   
2018   
2019   /* now we are ready to call the
2020      peep hole optimizer */
2021   if (!options.nopeep)
2022     peepHole (&lineHead);
2023   
2024   /* now do the actual printing */
2025   printLine (lineHead, codeOutFile);
2026   return;
2027 }