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