xa51, work in progress
[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, "r1l,[r0+2]");
278           sprintf (aop->name[1], "r1l");
279           emitcode (MOV, "r0,[r0]");
280           sprintf (aop->name[0], "r0");
281           return aop;
282         case 4:
283           emitcode (MOV, "r0,#%s", sym->rname);
284           emitcode (MOVC, "r1,[r0+2]");
285           sprintf (aop->name[1], "r1");
286           emitcode (MOVC, "r0,[r0]");
287           sprintf (aop->name[0], "r0");
288           return aop;
289         }
290       
291     } else {
292       aop->type=AOP_CODE;
293       emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
294       sprintf (aop->name[0], "[r0]");
295       if (size>2) {
296         sprintf (aop->name[1], "[r0+2]");
297       }
298     }
299     return aop;
300   }
301
302   // if in far space
303   if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
304     if (!canUsePointer) {
305       aop->type=AOP_REG;
306       switch (size) 
307         {
308         case 1:
309           emitcode (MOV, "r0,#%s", sym->rname);
310           emitcode (MOV, "r0l,[r0]");
311           sprintf (aop->name[0], "r0l");
312           return aop;
313         case 2:
314           emitcode (MOV, "r0,#%s", sym->rname);
315           emitcode (MOV, "r0,[r0]");
316           sprintf (aop->name[0], "r0");
317           return aop;
318         case 3:
319           emitcode (MOV, "r0,#%s", sym->rname);
320           emitcode (MOV, "r1l,[r0+2]");
321           sprintf (aop->name[1], "r1l");
322           emitcode (MOV, "r0,[r0]");
323           sprintf (aop->name[0], "r0");
324           return aop;
325         case 4:
326           emitcode (MOV, "r0,#%s", sym->rname);
327           emitcode (MOV, "r1,[r0+2]");
328           sprintf (aop->name[1], "r1");
329           emitcode (MOV, "r0,[r0]");
330           sprintf (aop->name[0], "r0");
331           return aop;
332         }
333     } else {
334       aop->type=AOP_FAR;
335       emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
336       sprintf (aop->name[0], "[r0]");
337       if (size>2) {
338         sprintf (aop->name[1], "[r0+2]");
339       }
340       return aop;
341     }
342   }
343   
344   bailOut("aopForSym");
345   return NULL;
346 }
347
348 /*-----------------------------------------------------------------*/
349 /* aopForVal - for a value                                         */
350 /*-----------------------------------------------------------------*/
351 static asmop *aopForVal(operand *op) {
352   asmop *aop;
353
354   if (IS_OP_LITERAL(op)) {
355     op->aop = aop = newAsmop (AOP_LIT);
356     switch ((aop->size=getSize(operandType(op))))
357       {
358       case 1:
359         sprintf (aop->name[0], "#0x%02x", 
360                  SPEC_CVAL(operandType(op)).v_int & 0xff);
361         sprintf (aop->name[1], "#0");
362         break;
363       case 2:
364         sprintf (aop->name[0], "#0x%04x", 
365                  SPEC_CVAL(operandType(op)).v_int & 0xffff);
366         sprintf (aop->name[1], "#0");
367         break;
368       case 3:
369         // must be a generic pointer, can only be zero
370         // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
371         sprintf (aop->name[0], "#0x%04x", 
372                  SPEC_CVAL(operandType(op)).v_uint & 0xffff);
373         sprintf (aop->name[1], "#0");
374         break;
375       case 4:
376         sprintf (aop->name[0], "#0x%04lx",
377                  SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
378         sprintf (aop->name[1], "#0x%04lx", 
379                  SPEC_CVAL(operandType(op)).v_ulong >> 16);
380         break;
381       default:
382         bailOut("aopForVal");
383       }
384     return aop;
385   }
386
387   // must be immediate
388   if (IS_SYMOP(op)) {
389     op->aop = aop = newAsmop (AOP_IMMD);
390     switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
391       {
392       case 1:
393       case 2:
394         sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
395         return aop;
396       case 3: // generic pointer
397         sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
398         sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
399         return aop;
400       }
401   }
402
403   bailOut ("aopForVal: unknown type");
404   return NULL;
405 }
406
407 static int aopOp(operand *op, 
408                   bool canUsePointer, bool canUseOffset) {
409
410   if (IS_SYMOP(op)) {
411     op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
412     return AOP_SIZE(op);
413   }
414   if (IS_VALOP(op)) {
415     op->aop=aopForVal (op);
416     return AOP_SIZE(op);
417   }
418
419   bailOut("aopOp: unexpected operand");
420   return 0;
421 }
422
423 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
424   if (strcmp(aop1->name[offset], aop2->name[offset])) {
425     return FALSE;
426   }
427   return TRUE;
428 }
429
430 bool aopIsDir(operand *op) {
431   return AOP_TYPE(op)==AOP_DIR;
432 }
433
434 bool aopIsBit(operand *op) {
435   return AOP_TYPE(op)==AOP_BIT;
436 }
437
438 bool aopIsPtr(operand *op) {
439   if (AOP_TYPE(op)==AOP_STK ||
440       AOP_TYPE(op)==AOP_CODE ||
441       AOP_TYPE(op)==AOP_FAR) {
442     return TRUE;
443   } else {
444     return FALSE;
445   }
446 }
447       
448 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
449
450   if (IS_SYMOP(op)) {
451     if (OP_SYMBOL(op)->onStack) {
452       sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
453       return opName;
454     }
455     if (IS_TRUE_SYMOP(op))
456       return OP_SYMBOL(op)->rname;
457     else if (OP_SYMBOL(op)->regs[offset])
458       return OP_SYMBOL(op)->regs[offset]->name;
459     else
460       bailOut("opRegName: unknown regs");
461   }
462
463   if (IS_VALOP(op)) {
464     switch (SPEC_NOUN(OP_VALUE(op)->type)) {
465     case V_SBIT:
466     case V_BIT:
467       if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
468           SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
469         bailOut("opRegName: invalid bit value");
470       }
471       // fall through
472     case V_CHAR:
473       sprintf (opName, "#%s0x%02x", decorate?"(char)":"", 
474                SPEC_CVAL(OP_VALUE(op)->type).v_int);
475       break;
476     case V_INT:
477       if (SPEC_LONG(OP_VALUE(op)->type)) {
478         sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
479                  SPEC_CVAL(OP_VALUE(op)->type).v_long);
480       } else {
481         sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
482                  SPEC_CVAL(OP_VALUE(op)->type).v_int);
483       }
484       break;
485     case V_FLOAT:
486       sprintf (opName, "#%s%f", decorate?"(float)":"",
487                SPEC_CVAL(OP_VALUE(op)->type).v_float);
488       break;
489     default: 
490       bailOut("opRegName: unexpected noun");
491     }
492     return opName;
493   }
494   bailOut("opRegName: unexpected operand type");
495   return NULL;
496 }
497
498 char * printOp (operand *op) {
499   static char line[132];
500   sym_link *optype=operandType(op);
501   bool isPtr = IS_PTR(optype);
502
503   if (IS_SYMOP(op)) {
504     symbol *sym=OP_SYMBOL(op);
505     if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
506       sym=SYM_SPIL_LOC(sym);
507     }
508     if (isPtr) {
509       sprintf (line, "[");
510       if (DCL_TYPE(optype)==FPOINTER)
511         strcat (line, "far * ");
512       else if (DCL_TYPE(optype)==CPOINTER)
513         strcat (line, "code * ");
514       else if (DCL_TYPE(optype)==GPOINTER)
515         strcat (line, "gen * ");
516       else if (DCL_TYPE(optype)==POINTER)
517         strcat (line, "near * ");
518       else
519         strcat (line, "unknown * ");
520       strcat (line, "(");
521       strcat (line, nounName(sym->etype));
522       strcat (line, ")");
523       strcat (line, sym->name);
524       strcat (line, "]:");
525     } else {
526       sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
527     }
528     if (sym->regs[0]) {
529       strcat (line, sym->regs[0]->name);
530       if (sym->regs[1]) {
531         strcat (line, ",");
532         strcat (line, sym->regs[1]->name);
533       }
534       return line;
535     }
536     if (sym->onStack) {
537       sprintf (line+strlen(line), "stack%+d", sym->stack);
538       return line;
539     }
540     if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
541       strcat (line, "code");
542       return line;
543     }
544     if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
545       strcat (line, "far");
546       return line;
547     }
548     if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
549       strcat (line, "bit");
550       return line;
551     }
552     if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
553       strcat (line, "dir");
554       return line;
555     }
556     strcat (line, "unknown");
557     return line;
558   } else if (IS_VALOP(op)) {
559     opRegName(op, 0, line, 1);
560   } else if (IS_TYPOP(op)) {
561     sprintf (line, "(");
562     if (isPtr) {
563       if (DCL_TYPE(optype)==FPOINTER)
564         strcat (line, "far * ");
565       else if (DCL_TYPE(optype)==CPOINTER)
566         strcat (line, "code * ");
567       else if (DCL_TYPE(optype)==GPOINTER)
568         strcat (line, "gen * ");
569       else if (DCL_TYPE(optype)==POINTER)
570         strcat (line, "near * ");
571       else
572         strcat (line, "unknown * ");
573     }
574     // forget about static, volatile, ... for now
575     if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
576     if (SPEC_LONG(operandType(op))) strcat (line, "long ");
577     strcat (line, nounName(operandType(op)));
578     strcat (line, ")");
579   } else {
580     bailOut("printOp: unexpected operand type");
581   }
582   return line;
583 }
584
585 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
586   char line[132];
587
588   sprintf (line, "%s(%d)", op, ic->lineno);
589   if (result) {
590     strcat (line, " result=");
591     strcat (line, printOp (IC_RESULT(ic)));
592   }
593   if (left) {
594     strcat (line, " left=");
595     strcat (line, printOp (IC_LEFT(ic)));
596   }
597   if (right) {
598     strcat (line, " right=");
599     strcat (line, printOp (IC_RIGHT(ic)));
600   }
601   emitcode (";", line);
602 }
603
604 /*-----------------------------------------------------------------*/
605 /* toBoolean - return carry for operand!=0                           */
606 /*-----------------------------------------------------------------*/
607 static char *toBoolean (operand * op) {
608   symbol *tlbl=newiTempLabel(NULL);
609
610   switch (AOP_SIZE(op)) 
611     {
612     case 1:
613     case 2:
614       emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
615                 "This needs a second thought");
616       
617       emitcode ("", "%05d$:", tlbl->key+100);
618       return "c";
619     }
620
621   bailOut("toBoolean: unknown size");
622   return NULL;
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* regsInCommon - two operands have some registers in common       */
627 /*-----------------------------------------------------------------*/
628 static bool regsInCommon (operand * op1, operand * op2) {
629   symbol *sym1, *sym2;
630   int i;
631
632   /* if they have registers in common */
633   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
634     return FALSE;
635
636   sym1 = OP_SYMBOL (op1);
637   sym2 = OP_SYMBOL (op2);
638
639   if (sym1->nRegs == 0 || sym2->nRegs == 0)
640     return FALSE;
641
642   for (i = 0; i < sym1->nRegs; i++)
643     {
644       int j;
645       if (!sym1->regs[i])
646         continue;
647
648       for (j = 0; j < sym2->nRegs; j++)
649         {
650           if (!sym2->regs[j])
651             continue;
652
653           if (sym2->regs[j] == sym1->regs[i])
654             return TRUE;
655         }
656     }
657
658   return FALSE;
659 }
660
661 /*-----------------------------------------------------------------*/
662 /* resultRemat - result  is rematerializable                       */
663 /*-----------------------------------------------------------------*/
664 static int resultRemat (iCode * ic) {
665   if (SKIP_IC (ic) || ic->op == IFX)
666     return 0;
667   
668   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
669     {
670       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
671       if (sym->remat && !POINTER_SET (ic))
672         return 1;
673     }
674   
675   return 0;
676 }
677
678 /*-----------------------------------------------------------------*/
679 /* genNot - generate code for ! operation                          */
680 /*-----------------------------------------------------------------*/
681 static void genNot (iCode * ic) {
682   printIc("genNot:", ic, 1,1,0);
683 }
684
685 /*-----------------------------------------------------------------*/
686 /* genCpl - generate code for complement                           */
687 /*-----------------------------------------------------------------*/
688 static void genCpl (iCode * ic) {
689   printIc("genCpl", ic, 1,1,0);
690 }
691
692 /*-----------------------------------------------------------------*/
693 /* genUminus - unary minus code generation                         */
694 /*-----------------------------------------------------------------*/
695 static void genUminus (iCode * ic) {
696   printIc("genUminus", ic, 1,1,0);
697 }
698
699 /*-----------------------------------------------------------------*/
700 /* genIpush - generate code for pushing                            */
701 /*-----------------------------------------------------------------*/
702 static void genIpush (iCode * ic) {
703   operand *left=IC_LEFT(ic);
704
705   printIc ("genIpush", ic, 0,1,0);
706   aopOp(left,FALSE,FALSE);
707
708
709   if (AOP_TYPE(left)==AOP_LIT) {
710     switch (AOP_SIZE(left)) 
711       {
712       case 1:
713         emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
714         emitcode ("push", "r1l");
715         _G.parmsPushed++;
716         return;
717       case 2:
718         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
719         emitcode ("push", "r1");
720         _G.parmsPushed++;
721         return;
722       case 3:
723         emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
724         emitcode ("push", "r1l");
725         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
726         emitcode ("push", "r1");
727         _G.parmsPushed += 2;
728         return;
729       case 4:
730         emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
731         emitcode ("push", "r1");
732         emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
733         emitcode ("push", "r1");
734         _G.parmsPushed += 2;
735         return;
736       }
737   } else {
738     if (AOP_SIZE(left)>2) {
739       emitcode ("push", "%s", AOP_NAME(left)[1]);
740       _G.parmsPushed++;
741     }
742     emitcode ("push", "%s", AOP_NAME(left)[0]);
743     _G.parmsPushed++;
744   }
745 }
746
747 /*-----------------------------------------------------------------*/
748 /* genIpop - recover the registers: can happen only for spilling   */
749 /*-----------------------------------------------------------------*/
750 static void genIpop (iCode * ic) {
751   printIc ("genIpop", ic, 0,1,0);
752 }
753
754 /*-----------------------------------------------------------------*/
755 /* genCall - generates a call statement                            */
756 /*-----------------------------------------------------------------*/
757 static void genCall (iCode * ic) {
758   operand *result=IC_RESULT(ic);
759
760   emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
761             OP_SYMBOL(IC_LEFT(ic))->name,
762             printOp (IC_RESULT(ic)));
763   emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
764
765   /* readjust the stack if we have pushed some parms */
766   if (_G.parmsPushed) {
767     emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
768     _G.parmsPushed=0;
769   }
770
771   /* if we need to assign a result value */
772   if (IS_ITEMP (IC_RESULT(ic)) &&
773       OP_SYMBOL (IC_RESULT (ic))->nRegs) {
774     aopOp(result,FALSE,FALSE);
775     switch (AOP_SIZE(result))
776       {
777       case 1:
778         emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
779         return;
780       case 2:
781         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
782         return;
783       case 3:
784         // generic pointer
785         emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
786         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
787         return;
788       case 4:
789         emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
790         emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
791         return;
792       }
793     bailOut("genCall");
794   }
795 }
796
797 /*-----------------------------------------------------------------*/
798 /* genPcall - generates a call by pointer statement                */
799 /*-----------------------------------------------------------------*/
800 static void
801 genPcall (iCode * ic)
802 {
803   emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* genFunction - generated code for function entry                 */
808 /*-----------------------------------------------------------------*/
809 static void genFunction (iCode * ic) {
810   symbol *sym=OP_SYMBOL(IC_LEFT(ic));
811   sym_link *type=sym->type;
812
813   emitcode (";", "genFunction %s", sym->rname);
814
815   /* print the allocation information */
816   printAllocInfo (currFunc, codeOutFile);
817
818   emitcode ("", "%s:", sym->rname);
819
820   if (IFFUNC_ISNAKED(type))
821   {
822       emitcode(";", "naked function: no prologue.");
823       return;
824   }
825
826   /* adjust the stack for locals used in this function */
827   if (sym->stack) {
828     emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
829   }
830 }
831
832 /*-----------------------------------------------------------------*/
833 /* genEndFunction - generates epilogue for functions               */
834 /*-----------------------------------------------------------------*/
835 static void
836 genEndFunction (iCode * ic)
837 {
838   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
839
840   printIc ("genEndFunction", ic, 0,0,0);
841
842   if (IFFUNC_ISNAKED(sym->type)) {
843       emitcode(";", "naked function: no epilogue.");
844       return;
845   }
846
847   /* readjust the stock for locals used in this function */
848   if (sym->stack) {
849     emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
850   }
851
852   if (IFFUNC_ISISR(sym->type)) {
853     emitcode ("reti", "");
854   } else {
855     emitcode ("ret", "");
856   }
857 }
858
859 /*-----------------------------------------------------------------*/
860 /* genRet - generate code for return statement                     */
861 /*-----------------------------------------------------------------*/
862 static void genRet (iCode * ic) {
863
864   printIc ("genRet", ic, 0,1,0);
865
866   aopOp(IC_LEFT(ic), TRUE, TRUE);
867
868   switch (AOP_SIZE(IC_LEFT(ic)))
869     {
870     case 4:
871       emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
872       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
873       break;
874     case 3:
875       emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
876       // fall through
877     case 2:
878       emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
879       break;
880     case 1:
881       emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
882       break;
883     default:
884       bailOut("genRet");
885     }
886   emitcode ("jmp", "%05d$", returnLabel->key+100);
887 }
888
889 /*-----------------------------------------------------------------*/
890 /* genLabel - generates a label                                    */
891 /*-----------------------------------------------------------------*/
892 static void genLabel (iCode * ic) {
893   /* special case never generate */
894   if (IC_LABEL (ic) == entryLabel)
895     return;
896
897   emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
898   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
899 }
900
901 /*-----------------------------------------------------------------*/
902 /* genGoto - generates a jmp                                      */
903 /*-----------------------------------------------------------------*/
904 static void genGoto (iCode * ic) {
905   emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* genPlus - generates code for addition                           */
911 /*-----------------------------------------------------------------*/
912 static void genPlus (iCode * ic) {
913   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
914   int size;
915   char *instr;
916
917   printIc ("genPlus", ic, 1,1,1);
918
919   size=aopOp(result, TRUE, TRUE);
920
921   /* if left is a literal, then exchange them */
922   if (IS_LITERAL(operandType(left))) {
923     operand *tmp = right;
924     right = left;
925     left = tmp;
926   }
927     
928   if (aopIsBit(result)) {
929     if (IS_LITERAL(operandType(right))) {
930       if (operandLitValue(right)) {
931         emitcode ("setb", AOP_NAME(result)[0]);
932         return;
933       }
934       aopOp(left, TRUE, TRUE);
935       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
936       return;
937     }
938     bailOut("genPlus: unfinished genPlus bit");
939   }
940   
941   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
942   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
943
944   if (size>1) {
945     instr="add.w";
946   } else {
947     instr="add.b";
948   }
949   if (!aopEqual(result->aop, left->aop, 0)) {
950     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
951   }
952   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
953   if (size>2) {
954     if (!aopEqual(result->aop, left->aop, 1)) {
955       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
956     }
957     if (size==3) {
958       // generic pointer
959     } else {
960       emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
961     }
962   }
963   return;
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* genMinus - generates code for subtraction                       */
968 /*-----------------------------------------------------------------*/
969 static void genMinus (iCode * ic) {
970   printIc ("genMinus", ic, 1,1,1);
971 }
972
973
974 /*-----------------------------------------------------------------*/
975 /* genMult - generates code for multiplication                     */
976 /*-----------------------------------------------------------------*/
977 static void genMult (iCode * ic) {
978   printIc ("genMult", ic, 1,1,1);
979 }
980
981 /*-----------------------------------------------------------------*/
982 /* genDiv - generates code for division                            */
983 /*-----------------------------------------------------------------*/
984 static void genDiv (iCode * ic) {
985   printIc ("genDiv", ic, 1,1,1);
986 }
987
988 /*-----------------------------------------------------------------*/
989 /* genMod - generates code for division                            */
990 /*-----------------------------------------------------------------*/
991 static void genMod (iCode * ic) {
992   printIc ("genMod", ic, 1,1,1);
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* genCmpGt :- greater than comparison                             */
997 /*-----------------------------------------------------------------*/
998 static void genCmpGt (iCode * ic) {
999   printIc ("genCmpGt", ic, 1,1,1);
1000 }
1001 /*-----------------------------------------------------------------*/
1002 /* genCmpGt :- greater than comparison                             */
1003 /*-----------------------------------------------------------------*/
1004 static void genCmpLe (iCode * ic) {
1005   printIc ("genCmpLe", ic, 1,1,1);
1006 }
1007 /*-----------------------------------------------------------------*/
1008 /* genCmpGt :- greater than comparison                             */
1009 /*-----------------------------------------------------------------*/
1010 static void genCmpGe (iCode * ic) {
1011   printIc ("genCmpGe", ic, 1,1,1);
1012 }
1013 /*-----------------------------------------------------------------*/
1014 /* genCmpGt :- greater than comparison                             */
1015 /*-----------------------------------------------------------------*/
1016 static void genCmpNe (iCode * ic) {
1017   printIc ("genCmpNe", ic, 1,1,1);
1018 }
1019 /*-----------------------------------------------------------------*/
1020 /* genCmpLt - less than comparisons                                */
1021 /*-----------------------------------------------------------------*/
1022 static void genCmpLt (iCode * ic) {
1023   printIc ("genCmpLt", ic, 1,1,1);
1024 }
1025 /*-----------------------------------------------------------------*/
1026 /* genCmpEq - generates code for equal to                          */
1027 /*-----------------------------------------------------------------*/
1028 static void genCmpEq (iCode * ic) {
1029   printIc ("genCmpEq", ic, 1,1,1);
1030 }
1031
1032 /*-----------------------------------------------------------------*/
1033 /* ifxForOp - returns the icode containing the ifx for operand     */
1034 /*-----------------------------------------------------------------*/
1035 static iCode *ifxForOp (operand * op, iCode * ic) {
1036   /* if true symbol then needs to be assigned */
1037   if (IS_TRUE_SYMOP (op))
1038     return NULL;
1039   
1040   /* if this has register type condition and
1041      the next instruction is ifx with the same operand
1042      and live to of the operand is upto the ifx only then */
1043   if (ic->next &&
1044       ic->next->op == IFX &&
1045       IC_COND (ic->next)->key == op->key &&
1046       OP_SYMBOL (op)->liveTo <= ic->next->seq)
1047     return ic->next;
1048   
1049   return NULL;
1050 }
1051
1052 /*-----------------------------------------------------------------*/
1053 /* hasInc - operand is incremented before any other use            */
1054 /*-----------------------------------------------------------------*/
1055 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1056   sym_link *type = operandType(op);
1057   sym_link *retype = getSpec (type);
1058   iCode *lic = ic->next;
1059   int isize ;
1060   
1061   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1062   if (!IS_SYMOP(op)) return NULL;
1063
1064   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1065   if (IS_AGGREGATE(type->next)) return NULL;
1066   if (osize != (isize = getSize(type->next))) return NULL;
1067
1068   while (lic) {
1069     /* if operand of the form op = op + <sizeof *op> */
1070     if (lic->op == '+') {
1071       if (isOperandEqual(IC_LEFT(lic),op) &&
1072           //isOperandEqual(IC_RESULT(lic),op) && 
1073           isOperandLiteral(IC_RIGHT(lic)) &&
1074           operandLitValue(IC_RIGHT(lic)) == isize) {
1075         emitcode (";", "Found hasInc");
1076         return lic;
1077       }
1078     }
1079     /* if the operand used or deffed */
1080     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1081       return NULL;
1082     }
1083     /* if GOTO or IFX */
1084     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1085     lic = lic->next;
1086   }
1087   return NULL;
1088 }
1089
1090 /*-----------------------------------------------------------------*/
1091 /* genAndOp - for && operation                                     */
1092 /*-----------------------------------------------------------------*/
1093 static void genAndOp (iCode * ic) {
1094   printIc ("genAndOp(&&)", ic, 1,1,1);
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* genOrOp - for || operation                                      */
1099 /*-----------------------------------------------------------------*/
1100 static void genOrOp (iCode * ic) {
1101   printIc ("genOrOp(||)", ic, 1,1,1);
1102 }
1103
1104 /*-----------------------------------------------------------------*/
1105 /* genAnd  - code for and                                            */
1106 /*-----------------------------------------------------------------*/
1107 static void genAnd (iCode * ic, iCode * ifx) {
1108   printIc ("genAnd", ic, 1,1,1);
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genOr  - code for or                                            */
1113 /*-----------------------------------------------------------------*/
1114 static void genOr (iCode * ic, iCode * ifx) {
1115   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1116   int size;
1117   char *instr;
1118
1119   printIc ("genOr", ic, 1,1,1);
1120
1121   size=aopOp(result, TRUE, TRUE);
1122
1123   /* if left is a literal, then exchange them */
1124   if (IS_LITERAL(operandType(left))) {
1125     operand *tmp = right;
1126     right = left;
1127     left = tmp;
1128   }
1129     
1130   if (aopIsBit(result)) {
1131     if (IS_LITERAL(operandType(right))) {
1132       if (operandLitValue(right)) {
1133         emitcode ("setb", AOP_NAME(result)[0]);
1134         return;
1135       }
1136       aopOp(left, TRUE, TRUE);
1137       emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1138       return;
1139     }
1140   }
1141   
1142   aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1143   aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1144
1145   if (size>1) {
1146     instr="or.w";
1147   } else {
1148     instr="or.b";
1149   }
1150   if (!aopEqual(result->aop, left->aop, 0)) {
1151     emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1152   }
1153   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1154   if (size>2) {
1155     if (!aopEqual(result->aop, left->aop, 1)) {
1156       emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1157     }
1158     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1159   }
1160   return;
1161 }
1162
1163 /*-----------------------------------------------------------------*/
1164 /* genXor - code for xclusive or                                   */
1165 /*-----------------------------------------------------------------*/
1166 static void genXor (iCode * ic, iCode * ifx) {
1167   printIc ("genXor", ic, 1,1,1);
1168 }
1169
1170 /*-----------------------------------------------------------------*/
1171 /* genInline - write the inline code out                           */
1172 /*-----------------------------------------------------------------*/
1173 static void genInline (iCode * ic) {
1174
1175   printIc ("genInline", ic, 0,0,0);
1176   
1177   emitcode ("", IC_INLINE(ic));
1178 }
1179
1180 /*-----------------------------------------------------------------*/
1181 /* genRRC - rotate right with carry                                */
1182 /*-----------------------------------------------------------------*/
1183 static void genRRC (iCode * ic) {
1184   printIc ("genRRC", ic, 1,1,0);
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* genRLC - generate code for rotate left with carry               */
1189 /*-----------------------------------------------------------------*/
1190 static void genRLC (iCode * ic) {
1191   printIc ("genRLC", ic, 1,1,0);
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* genGetHbit - generates code get highest order bit               */
1196 /*-----------------------------------------------------------------*/
1197 static void genGetHbit (iCode * ic) {
1198   printIc ("genGetHbit", ic, 1,1,0);
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* genLeftShift - generates code for left shifting                 */
1203 /*-----------------------------------------------------------------*/
1204 static void genLeftShift (iCode * ic) {
1205   printIc ("genLeftShift", ic, 1,1,1);
1206 }
1207
1208 /*-----------------------------------------------------------------*/
1209 /* genRightShift - generate code for right shifting                */
1210 /*-----------------------------------------------------------------*/
1211 static void genRightShift (iCode * ic) {
1212   printIc ("genRightShift", ic, 1,1,1);
1213 }
1214
1215 /*-----------------------------------------------------------------*/
1216 /* genPointerGet - generate code for pointer get                   */
1217 /*-----------------------------------------------------------------*/
1218 static void genPointerGet (iCode * ic, iCode *pi) {
1219   char *instr, *scratchReg;
1220   operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1221   bool codePointer=IS_CODEPTR(operandType(left));
1222   int size;
1223
1224   if (pi) {
1225     printIc ("genPointerGet pi", ic, 1,1,0);
1226   } else {
1227     printIc ("genPointerGet", ic, 1,1,0);
1228   }
1229
1230   if (!IS_PTR(operandType(left))) {
1231     bailOut ("genPointerGet: pointer required");
1232   }
1233
1234   aopOp(left,FALSE,FALSE);
1235   size=aopOp(result,TRUE,aopIsDir(left));
1236
1237   if (IS_GENPTR(operandType(left))) {
1238     symbol *tlbl1=newiTempLabel(NULL);
1239     symbol *tlbl2=newiTempLabel(NULL);
1240     emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1241     emitcode ("beq", "%05d$", tlbl1->key+100);
1242     // far/near pointer
1243     if (pi) {
1244       emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1245       pi->generated=1;
1246     } else {
1247       emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1248     }
1249     if (size>2) {
1250       if (pi) {
1251         emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1252       } else {
1253         emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1254       }
1255     }
1256     emitcode ("br", "%05d$", tlbl2->key+100);
1257     emitcode ("", "%05d$:", tlbl1->key+100);
1258     // code pointer
1259     if (pi) {
1260       emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1261       pi->generated=1;
1262     } else {
1263       emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1264       emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1265     }
1266     if (size>2) {
1267       if (pi) {
1268         emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1269       } else {
1270         emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1271       }
1272     }
1273     emitcode ("", "%05d$:", tlbl2->key+100);
1274     return;
1275   }
1276
1277   switch (AOP_TYPE(left)) 
1278     {
1279     case AOP_REG:
1280       if (size>1) {
1281         if (codePointer) {
1282           instr=MOVCW;
1283         } else {
1284           instr=MOVW;
1285         }
1286         scratchReg=R1;
1287       } else {
1288         if (codePointer) {
1289           instr=MOVCB;
1290         } else {
1291           instr=MOVB;
1292         }
1293         scratchReg=R1L;
1294       }
1295       if (AOP_TYPE(result)==AOP_STK) {
1296         emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1297         emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1298       } else {
1299         if (pi) {
1300           emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], 
1301                     AOP_NAME(left)[0]);
1302           pi->generated=1;
1303         } else {
1304           if (codePointer) {
1305             emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1306             emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1307           } else {
1308             emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], 
1309                       AOP_NAME(left)[0]);
1310           }
1311         }
1312       }
1313       if (size > 2) {
1314         if (size==3) {
1315           if (codePointer) {
1316             instr=MOVCB;
1317           } else {
1318             instr=MOVB;
1319           }
1320           scratchReg=R1L;
1321         }
1322         if (AOP_TYPE(result)==AOP_STK) {
1323           emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1324           emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1325         } else {
1326           if (pi) {
1327             emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1], 
1328                       AOP_NAME(left)[0]);
1329           } else {
1330             if (codePointer) {
1331               emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1332             } else {
1333               emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], 
1334                         AOP_NAME(left)[0]);
1335             }
1336           }
1337         }
1338       }
1339       return;
1340     }
1341   bailOut ("genPointerGet");
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* genPointerSet - stores the value into a pointer location        */
1346 /*-----------------------------------------------------------------*/
1347 static void genPointerSet (iCode * ic, iCode *pi) {
1348   char *instr;
1349   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1350   int size;
1351
1352   printIc ("genPointerSet", ic, 1,0,1);
1353
1354   if (!IS_PTR(operandType(result))) {
1355     bailOut ("genPointerSet: pointer required");
1356   }
1357
1358   aopOp(result,FALSE,FALSE);
1359   size=aopOp(right,FALSE, FALSE);
1360
1361   if (IS_GENPTR(operandType(result))) {
1362     emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s", 
1363               AOP_NAME(result)[0], AOP_NAME(result)[1],
1364               AOP_NAME(right)[0], AOP_NAME(right)[1]);
1365     return;
1366   }
1367
1368   switch (AOP_TYPE(right)) 
1369     {
1370     case AOP_LIT:
1371     case AOP_REG:
1372       if (size>1) {
1373         instr=MOVW;
1374       } else {
1375         instr=MOVB;
1376       }
1377       if (pi) {
1378         emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1379         pi->generated=1;
1380       } else {
1381         emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1382       }
1383       if (size > 2) {
1384         if (size==3) {
1385           instr=MOVB;
1386         }
1387         if (pi) {
1388           emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], 
1389                     AOP_NAME(right)[1]);
1390         } else {
1391           emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], 
1392                     AOP_NAME(right)[1]);
1393         }
1394       }
1395       return;
1396     }
1397   bailOut ("genPointerSet");
1398 }
1399
1400 /*-----------------------------------------------------------------*/
1401 /* genIfx - generate code for Ifx statement                        */
1402 /*-----------------------------------------------------------------*/
1403 static void genIfx (iCode * ic, iCode * popIc) {
1404   int size;
1405   char *instr;
1406   bool trueOrFalse;
1407   symbol *jlbl, *tlbl=newiTempLabel(NULL);
1408   operand *cond=IC_COND(ic);
1409
1410   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
1411             ic->lineno, printOp(cond),
1412             IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1413             IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1414
1415   size=aopOp(cond,TRUE,TRUE);
1416
1417   if (IC_TRUE(ic)) {
1418     trueOrFalse=TRUE;
1419     jlbl=IC_TRUE(ic);
1420   } else {
1421     trueOrFalse=FALSE;
1422     jlbl=IC_FALSE(ic);
1423   }
1424
1425   switch (AOP_TYPE(cond) )
1426     {
1427     case AOP_BIT:
1428       emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
1429                 AOP_NAME(cond)[0], tlbl->key+100);
1430       emitcode ("jmp", "%05d$", jlbl->key+100);
1431       emitcode ("", "%05d$:", tlbl->key+100);
1432       return;
1433     case AOP_REG:
1434     case AOP_DIR:
1435     case AOP_FAR:
1436     case AOP_STK:
1437       if (size>1) {
1438         instr="cmp.w";
1439       } else {
1440         instr="cmp.b";
1441       }
1442       emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1443       emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1444       if (size > 2) {
1445         if (size==3) {
1446           // generic pointer, forget the generic part
1447         } else {
1448           emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1449           emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1450         }
1451       }
1452       emitcode ("jmp", "%05d$", jlbl->key+100);
1453       emitcode ("", "%05d$:", tlbl->key+100);
1454       return;
1455     }
1456   bailOut ("genIfx");
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* genAddrOf - generates code for address of                       */
1461 /*-----------------------------------------------------------------*/
1462 static void genAddrOf (iCode * ic) {
1463   int size;
1464   operand *left=IC_LEFT(ic);
1465
1466   printIc ("genAddrOf", ic, 1,1,0);
1467
1468   size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1469
1470   if (isOperandOnStack(left)) {
1471     emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1472               getStackOffset(OP_SYMBOL(left)->stack));
1473     if (size > 2) {
1474       // this must be a generic pointer
1475       emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1476     }
1477     return;
1478   }
1479
1480   if (isOperandInDirSpace(left) ||
1481       isOperandInFarSpace(left) ||
1482       isOperandInCodeSpace(left)) {
1483     emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1484               OP_SYMBOL(left)->rname);
1485     if (size > 2) {
1486       // this must be a generic pointer
1487       int space=0; // dir space
1488       if (isOperandInFarSpace(left)) {
1489         space=1;
1490       } else if (isOperandInCodeSpace(left)) {
1491         space=2;
1492       }
1493       emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1494     }
1495     return;
1496   }
1497
1498   bailOut("genAddrOf");
1499 }
1500
1501 /*-----------------------------------------------------------------*/
1502 /* genAssign - generate code for assignment                        */
1503 /*-----------------------------------------------------------------*/
1504 static void genAssign (iCode * ic) {
1505   operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1506   int size;
1507   char *instr;
1508
1509   printIc ("genAssign", ic, 1,0,1);
1510   
1511   if (!IS_SYMOP(result)) {
1512     bailOut("genAssign: result is not a symbol");
1513   }
1514   
1515   aopOp(result, TRUE, TRUE);
1516   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1517   size=AOP_SIZE(result);
1518
1519   /* if result is a bit */
1520   if (AOP_TYPE(result) == AOP_BIT) {
1521     /* if right is literal, we know what the value is */
1522     if (AOP_TYPE(right) == AOP_LIT) {
1523       if (operandLitValue(right)) {
1524         emitcode ("setb", AOP_NAME(result)[0]);
1525       } else {
1526         emitcode ("clr", AOP_NAME(result)[0]);
1527       }
1528       return;
1529     }
1530     /* if right is also a bit */
1531     if (AOP_TYPE(right) == AOP_BIT) {
1532       emitcode ("mov", "c,%s", AOP_NAME(right));
1533       emitcode ("mov", "%s,c", AOP_NAME(result));
1534       return;
1535     }
1536     /* we need to or */
1537     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1538     return;
1539   }
1540
1541   /* general case */
1542   if (size>1) {
1543     instr=MOVW;
1544   } else {
1545     instr=MOVB;
1546   }
1547   emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1548
1549   if (size > 2) {
1550     if (size==3) {
1551       // generic pointer
1552       instr=MOVB;
1553     }
1554     emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1555     return;
1556   }
1557 }
1558
1559 /*-----------------------------------------------------------------*/
1560 /* genJumpTab - genrates code for jump table                       */
1561 /*-----------------------------------------------------------------*/
1562 static void genJumpTab (iCode * ic) {
1563   printIc ("genJumpTab", ic, 0,0,0);
1564 }
1565
1566 /*-----------------------------------------------------------------*/
1567 /* genCast - gen code for casting                                  */
1568 /*-----------------------------------------------------------------*/
1569 static void genCast (iCode * ic) {
1570   int size;
1571   operand *result=IC_RESULT(ic);
1572   operand *right=IC_RIGHT(ic);
1573   sym_link *ctype=operandType(IC_LEFT(ic));
1574   sym_link *rtype=operandType(IC_RIGHT(ic));
1575   sym_link *etype=getSpec(rtype);
1576   short ptrType, signedness;
1577
1578   printIc ("genCast", ic, 1,1,1);
1579
1580   aopOp(result, TRUE, TRUE);
1581   aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1582   size=AOP_SIZE(result);
1583   
1584   /* if result is a bit */
1585   if (AOP_TYPE(result) == AOP_BIT) {
1586     /* if right is literal, we know what the value is */
1587     if (AOP_TYPE(right) == AOP_LIT) {
1588       if (operandLitValue(right)) {
1589         emitcode ("setb", AOP_NAME(result)[0]);
1590       } else {
1591         emitcode ("clr", AOP_NAME(result)[0]);
1592       }
1593       return;
1594     }
1595     /* if right is also a bit */
1596     if (AOP_TYPE(right) == AOP_BIT) {
1597       emitcode ("mov", "c,%s", AOP_NAME(right));
1598       emitcode ("mov", "%s,c", AOP_NAME(result));
1599       return;
1600     }
1601     /* we need to or */
1602     emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1603     return;
1604   }
1605
1606   /* if right is a bit */
1607   if (AOP_TYPE(right)==AOP_BIT) {
1608     emitcode ("mov", "c,%s", AOP_NAME(right));
1609     emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1610     emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1611     if (size>2) {
1612       emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1613     }
1614     return;
1615   }
1616
1617   /* if the result is of type pointer */
1618   if (IS_PTR (ctype)) {
1619
1620     if (AOP_SIZE(right)>1) {
1621       emitcode ("mov", "%s,%s",  AOP_NAME(result)[0], AOP_NAME(right)[0]);
1622     } else {
1623       emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1624       emitcode ("sext", "r1h");
1625       emitcode ("mov", "%s,r1",  AOP_NAME(result)[0]);
1626     }
1627     
1628     /* if pointer to generic pointer */
1629     if (IS_GENPTR (ctype)) {
1630             
1631       if (IS_GENPTR (rtype)) {
1632         bailOut("genCast: gptr -> gptr");
1633       }
1634
1635       if (IS_PTR (rtype)) {
1636         ptrType = DCL_TYPE (rtype);
1637       } else {
1638         /* we have to go by the storage class */
1639         if (!SPEC_OCLS(etype)) {
1640           ptrType=0; // hush the compiler
1641           bailOut("genCast: unknown storage class");
1642         } else {
1643           ptrType = PTR_TYPE (SPEC_OCLS (etype));
1644         }
1645       }
1646       
1647       /* the generic part depends on the type */
1648       switch (ptrType)
1649         {
1650         case POINTER:
1651           emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
1652           break;
1653         case FPOINTER:
1654           emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
1655           break;
1656         case CPOINTER:
1657           emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
1658           break;
1659         default:
1660           bailOut("genCast: got unknown storage class");
1661         }
1662     }
1663     return;
1664   }
1665
1666   /* do we have to sign extend? */
1667   signedness = SPEC_USIGN(rtype);
1668
1669   /* now depending on the size */
1670   switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1671     {
1672     case 0x44:
1673     case 0x33:
1674       emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1675       // fall through
1676     case 0x24:
1677     case 0x22:
1678     case 0x11:
1679       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1680       return;
1681     case 0x42:
1682       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1683       if (signedness) {
1684         emitcode("sext", "%s", AOP_NAME(result)[1]);
1685       } else {
1686         emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1687       }
1688       return;
1689     case 0x41:
1690     case 0x21:
1691       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1692       if (signedness) {
1693         emitcode("sext", "r1h");
1694       } else {
1695         emitcode("mov", "r1h,#0");
1696       }
1697       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1698       if (size==2)
1699         return;
1700       // fall through: case 0x41
1701       emitcode("sext", AOP_NAME(result)[1]);
1702       return;
1703     case 0x14:
1704     case 0x12:
1705       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1706       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1707       return;
1708     }
1709   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1710           AOP_SIZE(result), AOP_SIZE(right));
1711   bailOut("genCast: unknown size");
1712 }
1713
1714
1715 /*-----------------------------------------------------------------*/
1716 /* genDjnz - generate decrement & jump if not zero instrucion      */
1717 /*-----------------------------------------------------------------*/
1718 static bool genDjnz (iCode * ic, iCode * ifx) {
1719   symbol *lbl, *lbl1;
1720
1721   if (!ifx)
1722     return 0;
1723
1724   /* if the if condition has a false label
1725      then we cannot save */
1726   if (IC_FALSE (ifx))
1727     return 0;
1728
1729   /* if the minus is not of the form
1730      a = a - 1 */
1731   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1732       !IS_OP_LITERAL (IC_RIGHT (ic)))
1733     return 0;
1734
1735   if (operandLitValue (IC_RIGHT (ic)) != 1)
1736     return 0;
1737
1738   /* if the size of this greater than two then no
1739      saving */
1740   if (getSize (operandType (IC_RESULT (ic))) > 2)
1741     return 0;
1742
1743   printIc ("genDjnz", ic, 1,1,1);
1744
1745   /* otherwise we can save BIG */
1746   lbl = newiTempLabel (NULL);
1747   lbl1 = newiTempLabel (NULL);
1748
1749   aopOp (IC_RESULT (ic), FALSE, TRUE);
1750
1751   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1752     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1753     emitcode ("br", "%05d$", lbl1->key + 100);
1754     emitcode ("", "%05d$:", lbl->key + 100);
1755     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1756     emitcode ("", "%05d$:", lbl1->key + 100);
1757     return TRUE;
1758   }
1759
1760   bailOut("genDjnz: aop type");
1761   return FALSE;
1762 }
1763
1764 /*-----------------------------------------------------------------*/
1765 /* genReceive - generate code for a receive iCode                  */
1766 /*-----------------------------------------------------------------*/
1767 static void genReceive (iCode * ic) {
1768   printIc ("genReceive", ic, 1,0,0);
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* gen51Code - generate code for 8051 based controllers            */
1773 /*-----------------------------------------------------------------*/
1774 void genXA51Code (iCode * lic) {
1775   iCode *ic;
1776   int cln = 0;
1777   
1778   lineHead = lineCurr = NULL;
1779   
1780   /* if debug information required */
1781   if (options.debug && currFunc)
1782     {
1783       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1784       _G.debugLine = 1;
1785       if (IS_STATIC (currFunc->etype))
1786         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1787       else
1788         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1789       _G.debugLine = 0;
1790     }
1791   
1792   for (ic = lic; ic; ic = ic->next) {
1793     if (ic->lineno && cln != ic->lineno) {
1794       if (options.debug) {
1795         _G.debugLine = 1;
1796         emitcode ("", "C$%s$%d$%d$%d ==.",
1797                   FileBaseName (ic->filename), ic->lineno,
1798                   ic->level, ic->block);
1799         _G.debugLine = 0;
1800       }
1801       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1802                 printCLine(ic->filename, ic->lineno));
1803       cln = ic->lineno;
1804     }
1805     /* if the result is marked as
1806        spilt and rematerializable or code for
1807        this has already been generated then
1808        do nothing */
1809     if (resultRemat (ic) || ic->generated)
1810       continue;
1811     
1812     /* depending on the operation */
1813     switch (ic->op)
1814       {
1815       case '!':
1816         genNot (ic);
1817         break;
1818         
1819       case '~':
1820         genCpl (ic);
1821         break;
1822         
1823       case UNARYMINUS:
1824         genUminus (ic);
1825         break;
1826         
1827       case IPUSH:
1828         genIpush (ic);
1829         break;
1830         
1831       case IPOP:
1832         /* IPOP happens only when trying to restore a
1833            spilt live range, if there is an ifx statement
1834            following this pop then the if statement might
1835            be using some of the registers being popped which
1836            would destory the contents of the register so
1837            we need to check for this condition and handle it */
1838         if (ic->next &&
1839             ic->next->op == IFX &&
1840             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1841           genIfx (ic->next, ic);
1842         else
1843           genIpop (ic);
1844         break;
1845         
1846       case CALL:
1847         genCall (ic);
1848         break;
1849         
1850       case PCALL:
1851         genPcall (ic);
1852         break;
1853         
1854       case FUNCTION:
1855         genFunction (ic);
1856         break;
1857         
1858       case ENDFUNCTION:
1859         genEndFunction (ic);
1860         break;
1861         
1862       case RETURN:
1863         genRet (ic);
1864         break;
1865         
1866       case LABEL:
1867         genLabel (ic);
1868         break;
1869         
1870       case GOTO:
1871         genGoto (ic);
1872         break;
1873         
1874       case '+':
1875         genPlus (ic);
1876         break;
1877         
1878       case '-':
1879         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1880           genMinus (ic);
1881         break;
1882         
1883       case '*':
1884         genMult (ic);
1885         break;
1886         
1887       case '/':
1888         genDiv (ic);
1889         break;
1890         
1891       case '%':
1892         genMod (ic);
1893         break;
1894         
1895       case '>':
1896         genCmpGt (ic);
1897         break;
1898         
1899       case '<':
1900         genCmpLt (ic);
1901         break;
1902         
1903       case LE_OP:
1904         genCmpLe (ic);
1905         break;
1906
1907       case GE_OP:
1908         genCmpGe (ic);
1909         break;
1910
1911       case NE_OP:
1912         genCmpNe (ic);
1913         break;
1914
1915       case EQ_OP:
1916         genCmpEq (ic);
1917         break;
1918         
1919       case AND_OP:
1920         genAndOp (ic);
1921         break;
1922         
1923       case OR_OP:
1924         genOrOp (ic);
1925         break;
1926         
1927       case '^':
1928         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1929         break;
1930         
1931       case '|':
1932         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1933         break;
1934         
1935       case BITWISEAND:
1936         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1937         break;
1938         
1939       case INLINEASM:
1940         genInline (ic);
1941         break;
1942         
1943       case RRC:
1944         genRRC (ic);
1945         break;
1946         
1947       case RLC:
1948         genRLC (ic);
1949         break;
1950         
1951       case GETHBIT:
1952         genGetHbit (ic);
1953         break;
1954         
1955       case LEFT_OP:
1956         genLeftShift (ic);
1957         break;
1958         
1959       case RIGHT_OP:
1960         genRightShift (ic);
1961         break;
1962         
1963       case GET_VALUE_AT_ADDRESS:
1964         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1965         break;
1966         
1967       case '=':
1968         if (POINTER_SET (ic))
1969           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1970         else
1971           genAssign (ic);
1972         break;
1973         
1974       case IFX:
1975         genIfx (ic, NULL);
1976         break;
1977         
1978       case ADDRESS_OF:
1979         genAddrOf (ic);
1980         break;
1981         
1982       case JUMPTABLE:
1983         genJumpTab (ic);
1984         break;
1985         
1986       case CAST:
1987         genCast (ic);
1988         break;
1989         
1990       case RECEIVE:
1991         genReceive (ic);
1992         break;
1993         
1994       case SEND:
1995         addSet (&_G.sendSet, ic);
1996         break;
1997         
1998       default:
1999         ic = ic;
2000       }
2001   }
2002   
2003   
2004   /* now we are ready to call the
2005      peep hole optimizer */
2006   if (!options.nopeep)
2007     peepHole (&lineHead);
2008   
2009   /* now do the actual printing */
2010   printLine (lineHead, codeOutFile);
2011   return;
2012 }