*** empty log message ***
[fw/sdcc] / src / xa51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26 -------------------------------------------------------------------------*/
27
28 //#define D(x)
29 #define D(x) x
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
43 #else
44 #ifdef HAVE_ENDIAN_H
45 #include <endian.h>
46 #else
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
50 #endif
51 #endif
52 #endif
53 #endif
54
55 #include "common.h"
56 #include "SDCCpeeph.h"
57 #include "ralloc.h"
58 #include "gen.h"
59
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
62 #else
63 #define STRCASECMP strcasecmp
64 #endif
65
66 extern int allocInfo;
67
68 /* this is the down and dirty file with all kinds of
69    kludgy & hacky stuff. This is what it is all about
70    CODE GENERATION for a specific MCU . some of the
71    routines may be reusable, will have to see */
72
73 static struct
74   {
75     short inLine;
76     short debugLine;
77     short stackExtend;
78     short nRegsSaved;
79     short parmsPushed;
80     set *sendSet;
81   }
82 _G;
83
84 extern int xa51_ptrRegReq;
85 extern int xa51_nRegs;
86 extern FILE *codeOutFile;
87
88 static lineNode *lineHead = NULL;
89 static lineNode *lineCurr = NULL;
90
91 #define LSB     0
92 #define MSB16   1
93 #define MSB24   2
94 #define MSB32   3
95
96 static char *MOV="mov";
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 static char *MOVC="movc";
100 static char *MOVCB="movc.b";
101 static char *MOVCW="movc.w";
102
103 static char *R1L="r1l";
104 static char *R1="r1";
105
106 void bailOut (char *mesg) {
107   fprintf (stderr, "%s: bailing out\n", mesg);
108   exit (1);
109 }
110
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple    */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst, char *fmt,...) {
115   va_list ap;
116   char lb[INITIAL_INLINEASM];
117   char *lbp = lb;
118
119   va_start (ap, fmt);
120
121   if (inst && *inst)
122     {
123       if (fmt && *fmt)
124         sprintf (lb, "%s\t", inst);
125       else
126         sprintf (lb, "%s", inst);
127       vsprintf (lb + (strlen (lb)), fmt, ap);
128     }
129   else
130     vsprintf (lb, fmt, ap);
131
132   while (isspace ((int)*lbp))
133     lbp++;
134
135   if (lbp && *lbp)
136     lineCurr = (lineCurr ?
137                 connectLine (lineCurr, newLineNode (lb)) :
138                 (lineHead = newLineNode (lb)));
139   lineCurr->isInline = _G.inLine;
140   lineCurr->isDebug = _G.debugLine;
141   va_end (ap);
142 }
143
144 char *getStackOffset(int stack) {
145   static char gsoBuf[1024];
146   sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
147            currFunc->stack, _G.nRegsSaved);
148   return gsoBuf;
149 }
150
151 /*-----------------------------------------------------------------*/
152 /* newAsmop - creates a new asmOp                                  */
153 /*-----------------------------------------------------------------*/
154 static asmop *
155 newAsmop (short type)
156 {
157   asmop *aop;
158
159   aop = Safe_calloc (1, sizeof (asmop));
160   aop->type = type;
161   return aop;
162 }
163
164 char *aopTypeName(asmop *aop) {
165   switch (aop->type)
166     {
167     case AOP_LIT: return "lit";
168     case AOP_REG: return "reg";
169     case AOP_DIR: return "dir";
170     case AOP_FAR: return "far";
171     case AOP_CODE: return "code";
172     case AOP_GPTR: return "gptr";
173     case AOP_STK: return "stack";
174     case AOP_IMMD: return "imm";
175     case AOP_BIT: return "bit";
176     }
177   return "unknown";
178 }
179
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol                                   */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym, 
184                         bool canUsePointer, bool canUseOffset) {
185   int size;
186   asmop *aop;
187
188   sym->aop = aop = newAsmop(0);
189   size=aop->size=getSize(sym->type);
190
191   // if the sym has registers
192   if (sym->nRegs && sym->regs[0]) {
193     aop->type=AOP_REG;
194     sprintf (aop->name[0], sym->regs[0]->name);
195     if (size > 2) {
196       sprintf (aop->name[1], sym->regs[1]->name);
197     }
198     return aop;
199   }
200
201   // if it is on stack
202   if (sym->onStack) {
203     if (!canUsePointer || !canUseOffset) {
204       aop->type=AOP_REG;
205       switch (size) 
206         {
207         case 1:
208           emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
209           sprintf (aop->name[0], "r0l");
210           return aop;
211         case 2:
212           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
213           sprintf (aop->name[0], "r0");
214           return aop;
215         case 3:
216           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
217           sprintf (aop->name[0], "r0");
218           emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
219           sprintf (aop->name[1], "r1l");
220           return aop;
221         case 4:
222           emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
223           sprintf (aop->name[0], "r0");
224           emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
225           sprintf (aop->name[1], "r1");
226           return aop;
227         }
228     }
229     aop->type=AOP_STK;
230     sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
231     if (size > 2) {
232       sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
233     }
234     return aop;
235   }
236
237   // if it has a spillLoc
238   if (sym->usl.spillLoc) {
239     return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
240   }
241
242   // if in bit space
243   if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
244     aop->type=AOP_BIT;
245     sprintf (aop->name[0], sym->rname);
246     return aop;
247   }
248
249   // if in direct space
250   if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
251     aop->type=AOP_DIR;
252     sprintf (aop->name[0], sym->rname);
253     if (size>2) {
254       sprintf (aop->name[1], "%s+2", sym->rname);
255     }
256     return aop;
257   }
258
259   // if in code space
260   if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261     if (!canUsePointer) {
262       aop->type=AOP_REG;
263       switch (size) 
264         {
265         case 1:
266           emitcode (MOV, "r0,#%s", sym->rname);
267           emitcode (MOVC, "r0l,[r0]");
268           sprintf (aop->name[0], "r0l");
269           return aop;
270         case 2:
271           emitcode (MOV, "r0,#%s", sym->rname);
272           emitcode (MOVC, "r0,[r0]");
273           sprintf (aop->name[0], "r0");
274           return aop;
275         case 3:
276           emitcode (MOV, "r0,#%s", sym->rname);
277           emitcode (MOVC, "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       if (signedness) {
1702         emitcode("sext", "r1");
1703       } else {
1704         emitcode("mov", "r1,#0");
1705       }
1706       emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1707       return;
1708     case 0x14:
1709     case 0x12:
1710       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1711       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1712       return;
1713     }
1714   fprintf(stderr, "genCast: unknown size: %d:%d\n",
1715           AOP_SIZE(result), AOP_SIZE(right));
1716   bailOut("genCast: unknown size");
1717 }
1718
1719
1720 /*-----------------------------------------------------------------*/
1721 /* genDjnz - generate decrement & jump if not zero instrucion      */
1722 /*-----------------------------------------------------------------*/
1723 static bool genDjnz (iCode * ic, iCode * ifx) {
1724   symbol *lbl, *lbl1;
1725
1726   if (!ifx)
1727     return 0;
1728
1729   /* if the if condition has a false label
1730      then we cannot save */
1731   if (IC_FALSE (ifx))
1732     return 0;
1733
1734   /* if the minus is not of the form
1735      a = a - 1 */
1736   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1737       !IS_OP_LITERAL (IC_RIGHT (ic)))
1738     return 0;
1739
1740   if (operandLitValue (IC_RIGHT (ic)) != 1)
1741     return 0;
1742
1743   /* if the size of this greater than two then no
1744      saving */
1745   if (getSize (operandType (IC_RESULT (ic))) > 2)
1746     return 0;
1747
1748   printIc ("genDjnz", ic, 1,1,1);
1749
1750   /* otherwise we can save BIG */
1751   lbl = newiTempLabel (NULL);
1752   lbl1 = newiTempLabel (NULL);
1753
1754   aopOp (IC_RESULT (ic), FALSE, TRUE);
1755
1756   if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1757     emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1758     emitcode ("br", "%05d$", lbl1->key + 100);
1759     emitcode ("", "%05d$:", lbl->key + 100);
1760     emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1761     emitcode ("", "%05d$:", lbl1->key + 100);
1762     return TRUE;
1763   }
1764
1765   bailOut("genDjnz: aop type");
1766   return FALSE;
1767 }
1768
1769 /*-----------------------------------------------------------------*/
1770 /* genReceive - generate code for a receive iCode                  */
1771 /*-----------------------------------------------------------------*/
1772 static void genReceive (iCode * ic) {
1773   printIc ("genReceive", ic, 1,0,0);
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* gen51Code - generate code for 8051 based controllers            */
1778 /*-----------------------------------------------------------------*/
1779 void genXA51Code (iCode * lic) {
1780   iCode *ic;
1781   int cln = 0;
1782   
1783   lineHead = lineCurr = NULL;
1784   
1785   /* if debug information required */
1786   if (options.debug && currFunc)
1787     {
1788       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1789       _G.debugLine = 1;
1790       if (IS_STATIC (currFunc->etype))
1791         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1792       else
1793         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1794       _G.debugLine = 0;
1795     }
1796   
1797   for (ic = lic; ic; ic = ic->next) {
1798     if (ic->lineno && cln != ic->lineno) {
1799       if (options.debug) {
1800         _G.debugLine = 1;
1801         emitcode ("", "C$%s$%d$%d$%d ==.",
1802                   FileBaseName (ic->filename), ic->lineno,
1803                   ic->level, ic->block);
1804         _G.debugLine = 0;
1805       }
1806       emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
1807                 printCLine(ic->filename, ic->lineno));
1808       cln = ic->lineno;
1809     }
1810     /* if the result is marked as
1811        spilt and rematerializable or code for
1812        this has already been generated then
1813        do nothing */
1814     if (resultRemat (ic) || ic->generated)
1815       continue;
1816     
1817     /* depending on the operation */
1818     switch (ic->op)
1819       {
1820       case '!':
1821         genNot (ic);
1822         break;
1823         
1824       case '~':
1825         genCpl (ic);
1826         break;
1827         
1828       case UNARYMINUS:
1829         genUminus (ic);
1830         break;
1831         
1832       case IPUSH:
1833         genIpush (ic);
1834         break;
1835         
1836       case IPOP:
1837         /* IPOP happens only when trying to restore a
1838            spilt live range, if there is an ifx statement
1839            following this pop then the if statement might
1840            be using some of the registers being popped which
1841            would destory the contents of the register so
1842            we need to check for this condition and handle it */
1843         if (ic->next &&
1844             ic->next->op == IFX &&
1845             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1846           genIfx (ic->next, ic);
1847         else
1848           genIpop (ic);
1849         break;
1850         
1851       case CALL:
1852         genCall (ic);
1853         break;
1854         
1855       case PCALL:
1856         genPcall (ic);
1857         break;
1858         
1859       case FUNCTION:
1860         genFunction (ic);
1861         break;
1862         
1863       case ENDFUNCTION:
1864         genEndFunction (ic);
1865         break;
1866         
1867       case RETURN:
1868         genRet (ic);
1869         break;
1870         
1871       case LABEL:
1872         genLabel (ic);
1873         break;
1874         
1875       case GOTO:
1876         genGoto (ic);
1877         break;
1878         
1879       case '+':
1880         genPlus (ic);
1881         break;
1882         
1883       case '-':
1884         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1885           genMinus (ic);
1886         break;
1887         
1888       case '*':
1889         genMult (ic);
1890         break;
1891         
1892       case '/':
1893         genDiv (ic);
1894         break;
1895         
1896       case '%':
1897         genMod (ic);
1898         break;
1899         
1900       case '>':
1901         genCmpGt (ic);
1902         break;
1903         
1904       case '<':
1905         genCmpLt (ic);
1906         break;
1907         
1908       case LE_OP:
1909         genCmpLe (ic);
1910         break;
1911
1912       case GE_OP:
1913         genCmpGe (ic);
1914         break;
1915
1916       case NE_OP:
1917         genCmpNe (ic);
1918         break;
1919
1920       case EQ_OP:
1921         genCmpEq (ic);
1922         break;
1923         
1924       case AND_OP:
1925         genAndOp (ic);
1926         break;
1927         
1928       case OR_OP:
1929         genOrOp (ic);
1930         break;
1931         
1932       case '^':
1933         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1934         break;
1935         
1936       case '|':
1937         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1938         break;
1939         
1940       case BITWISEAND:
1941         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1942         break;
1943         
1944       case INLINEASM:
1945         genInline (ic);
1946         break;
1947         
1948       case RRC:
1949         genRRC (ic);
1950         break;
1951         
1952       case RLC:
1953         genRLC (ic);
1954         break;
1955         
1956       case GETHBIT:
1957         genGetHbit (ic);
1958         break;
1959         
1960       case LEFT_OP:
1961         genLeftShift (ic);
1962         break;
1963         
1964       case RIGHT_OP:
1965         genRightShift (ic);
1966         break;
1967         
1968       case GET_VALUE_AT_ADDRESS:
1969         genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1970         break;
1971         
1972       case '=':
1973         if (POINTER_SET (ic))
1974           genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1975         else
1976           genAssign (ic);
1977         break;
1978         
1979       case IFX:
1980         genIfx (ic, NULL);
1981         break;
1982         
1983       case ADDRESS_OF:
1984         genAddrOf (ic);
1985         break;
1986         
1987       case JUMPTABLE:
1988         genJumpTab (ic);
1989         break;
1990         
1991       case CAST:
1992         genCast (ic);
1993         break;
1994         
1995       case RECEIVE:
1996         genReceive (ic);
1997         break;
1998         
1999       case SEND:
2000         addSet (&_G.sendSet, ic);
2001         break;
2002         
2003       default:
2004         ic = ic;
2005       }
2006   }
2007   
2008   
2009   /* now we are ready to call the
2010      peep hole optimizer */
2011   if (!options.nopeep)
2012     peepHole (&lineHead);
2013   
2014   /* now do the actual printing */
2015   printLine (lineHead, codeOutFile);
2016   return;
2017 }