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